Definire l'handler delle funzioni Lambda in Node.js
Il gestore di funzioni Lambda è il metodo nel codice della funzione che elabora gli eventi. Quando viene richiamata la funzione, Lambda esegue il metodo del gestore. La funzione viene eseguita fino a quando il gestore non restituisce una risposta, termina o scade.
Questa pagina descrive come lavorare con i gestori di funzioni Lambda in Go, inclusa la configurazione del progetto, le convenzioni di denominazione e le migliori pratiche. Questa pagina include anche un esempio di funzione Go Lambda che raccoglie informazioni su un ordine, produce una ricevuta in un file di testo e inserisce questo file in un bucket Amazon Simple Storage Service (S3). Per informazioni su come distribuire una funzione dopo averla scritta, consulta o. Distribuisci funzioni Lambda in Node.js con archivi di file .zip Distribuisci funzioni Lambda in Node.js con immagini di container
Argomenti
Configurazione di Go Handler
Esistono diversi modi per inizializzare un progetto Lambda Node.js. Ad esempio, è possibile creare un progetto Node.js standard utilizzandonpm, creare un'AWS SAMapplicazione o creare un'AWS CDKapplicazione.
Per creare il progetto utilizzandonpm:
npm init
Questo comando inizializza il progetto e genera il package.json file che elenca le dipendenze del progetto.
Il codice della funzione risiede in un file .js o in .mjs JavaScript. In questo esempio viene assegnato un nome a questo file index.mjs perché utilizza un gestore del modulo ES. Lambda supporta sia il modulo ES che i gestori CommonJS. Per ulteriori informazioni, consulta Impostazione di un gestore di funzioni come modulo ES.
Un tipico progetto di funzione Lambda di Node.js segue questa struttura generale:
/project-root ├── index.mjs — Contains main handler ├── package.json — Project metadata and dependencies ├── package-lock.json — Dependency lock file └── node_modules/ — Installed dependencies
Esempio di codice della funzione Lambda
Il seguente esempio di codice della funzione Go Lambda raccoglie le informazioni su un ordine, produce una ricevuta in un file di testo e inserisce questo file in un bucket Amazon S3.
Nota
Questo esempio utilizza un gestore di moduli ES. Lambda supporta sia il modulo ES che i gestori CommonJS. Per ulteriori informazioni, consulta Impostazione di un gestore di funzioni come modulo ES.
Esempio funzione Lambda index.mjs
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'; // Initialize the S3 client outside the handler for reuse const s3Client = new S3Client(); /** * Lambda handler for processing orders and storing receipts in S3. * @param {Object} event - Input event containing order details * @param {string} event.order_id - The unique identifier for the order * @param {number} event.amount - The order amount * @param {string} event.item - The item purchased * @returns {Promise<string>} Success message */ export const handler = async(event) => { try { // Access environment variables const bucketName = process.env.RECEIPT_BUCKET; if (!bucketName) { throw new Error('RECEIPT_BUCKET environment variable is not set'); } // Create the receipt content and key destination const receiptContent = `OrderID: ${event.order_id}\nAmount: $${event.amount.toFixed(2)}\nItem: ${event.item}`; const key = `receipts/${event.order_id}.txt`; // Upload the receipt to S3 await uploadReceiptToS3(bucketName, key, receiptContent); console.log(`Successfully processed order ${event.order_id} and stored receipt in S3 bucket ${bucketName}`); return 'Success'; } catch (error) { console.error(`Failed to process order: ${error.message}`); throw error; } }; /** * Helper function to upload receipt to S3 * @param {string} bucketName - The S3 bucket name * @param {string} key - The S3 object key * @param {string} receiptContent - The content to upload * @returns {Promise<void>} */ async function uploadReceiptToS3(bucketName, key, receiptContent) { try { const command = new PutObjectCommand({ Bucket: bucketName, Key: key, Body: receiptContent }); await s3Client.send(command); } catch (error) { throw new Error(`Failed to upload receipt to S3: ${error.message}`); } }
Questo file index.mjs contiene le sezioni seguenti:
-
Blocco : utilizza questo blocco per includere le librerie richieste dalla funzione Lambda.
-
const s3Clientdichiarazione: inizializza un client Amazon S3 al di fuori della funzione di gestione. Ciò fa sì che Lambda esegua questo codice durante la fase di inizializzazione e il client viene preservato per il riutilizzo su più chiamate. -
export const handler: in questa fase, Lambda invoca il gestore della funzione. Quando distribuisci la tua funzione, specifica la proprietà Handler.index.handlerIl valore dellaHandlerproprietà è costituito dal nome del file e dal nome del metodo dell'handler esportato, separati da un punto. -
uploadReceiptToS3funzione: Questa è una funzione di supporto a cui fa riferimento la funzione di gestione principale.
Affinché questa funzione funzioni correttamente, il suo ruolo di esecuzione deve consentire l's3:PutObjectazione. Inoltre, assicuratevi di definire la variabile di RECEIPT_BUCKET ambiente. Dopo una chiamata riuscita, il bucket Amazon S3 dovrebbe contenere un file di ricevuta.
Convenzioni di denominazione dei gestori
Quando si configura una funzione, il valore dell'impostazione dell'handler è costituito dal nome del file e dal nome del metodo dell'handler esportato, separati da un punto. L'impostazione predefinita per le funzioni create nella console e negli esempi in questa guida è index.handler. Questo indica il metodo handler che viene esportato dal file index.js o index.mjs.
Se si crea una funzione nella console utilizzando un nome di file o un nome del gestore di funzione diverso, è necessario modificare il nome del gestore predefinito.
Modifica del nome del gestore funzioni (console)
-
Apri la pagina Funzioni
della console Lambda e scegli la tua funzione. -
Scegli la scheda Codice.
-
Scorri verso il basso fino al riquadro Impostazioni di runtime e scegli Modifica.
-
In Gestore, inserisci il nuovo nome per il tuo gestore di funzioni.
-
Selezionare Salva.
Definizione e accesso all'oggetto evento di input
JSON è il formato di input più comune e standard per le funzioni Lambda. In questo esempio, la funzione prevede un input simile a quanto segue:
{ "order_id": "12345", "amount": 199.99, "item": "Wireless Headphones" }
Quando si utilizzano le funzioni Lambda in Go, è possibile definire la forma dell'evento di input previsto come struttura Go. In questo esempio, definiamo la struttura di input nel commento JSDoc del gestore:
/** * Lambda handler for processing orders and storing receipts in S3. * @param {Object} event - Input event containing order details * @param {string} event.order_id - The unique identifier for the order * @param {number} event.amount - The order amount * @param {string} event.item - The item purchased * @returns {Promise<string>} Success message */
Dopo aver definito questi tipi nel commento JSDoc, puoi accedere ai campi dell'oggetto evento direttamente nel codice. Ad esempio, event.order_id recupera il valore di order_id dall'input originale.
Modelli di gestione validi per le funzioni Node.js
Per dichiarare il gestore della funzione è consigliato l'utilizzo di async/await, anziché di quello dei richiami. Async/await è un modo conciso e leggibile per scrivere codice asincrono in Node.js, senza la necessità di richiami nidificati o di concatenamento di promesse. Con async/await puoi scrivere codice che si legga come codice sincrono, pur rimanendo asincrono e privo di blocchi.
Usare async/await (consigliato)
La parola chiave async contrassegna una funzione come asincrona, mentre la parola chiave await mette in pausa l'esecuzione della funzione fino alla risoluzione di Promise. Il comando accetta gli argomenti seguenti:
-
event: contiene i dati di input passati alla funzione. -
Questo oggetto di contesto contiene informazioni sull'invocazione, sulla funzione e sull'ambiente di esecuzione. Per ulteriori informazioni, consulta Utilizzo dell'oggetto di contesto Lambda per recuperare le informazioni sulla funzione Node.js.
Ecco le firme valide per il pattern async/await:
export const handler = async(event)=> { };export const handler = async(event, context)=> { };
Nota
Utilizza un ambiente di sviluppo integrato (IDE) locale, un editor di testo o per scrivere il codice della funzione TypeScript. Non è possibile creare il codice TypeScript sulla console Lambda.
Utilizzo dei richiami
I gestori di callback devono utilizzare gli argomenti event, context e callback. Esempio:
export const handler =(event, context, callback)=> { };
La funzione di callback prevede una risposta Error e una, che deve essere serializzabile in formato JSON. Quando utilizzi i richiami nel gestore, la funzione continua ad essere eseguita finché il ciclo di eventi
Esempio – richiesta HTTP con callback
La seguente funzione di esempio controlla un URL e restituisce il codice di stato all'invoker.
import https from "https"; let url = "https://aws.amazon.com/"; export const handler = (event, context, callback) => { https.get(url, (res) => { callback(null, res.statusCode); }).on("error", (e) => { callback(Error(e)); }); };
Utilizzo dell'SDK per JavaScript v3 nel gestore
Spesso, utilizzerai le funzioni Lambda per interagire o aggiornare altre AWS risorse. Il modo più semplice per interfacciarsi con queste risorse è usare la AWS SDK per JavaScript v2. Tutti i runtime Lambda Node.js supportati includono l'SDK per JavaScript versione 3. Tuttavia, consigliamo fortemente di includere i client AWS SDK necessari nel pacchetto di distribuzione. Ciò massimizza la compatibilità con le versioni precedenti durante i futuri aggiornamenti del runtime Lambda. Affidati all'SDK fornito in fase di esecuzione solo quando non puoi includere pacchetti aggiuntivi (ad esempio, quando usi l'editor di codice della console Lambda o il codice in linea in un modello). AWS CloudFormation
Per aggiungere dipendenze SDK alla tua funzione, usa il npm install comando per i client SDK specifici di cui hai bisogno. Nel codice di esempio, abbiamo usato il client Amazon S3. Aggiungi queste dipendenze eseguendo i seguenti comandi nella directory che contiene i file e :
npm install @aws-sdk/client-s3
Nel codice della funzione, importa il client e i comandi di cui hai bisogno, come dimostra la funzione di esempio:
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
Quindi, inizializza un client Amazon S3:
const s3Client = new S3Client();
In questo esempio, abbiamo inizializzato il nostro client Amazon S3 nella funzione per evitare di doverlo inizializzare ogni volta che richiamiamo la nostra funzione. Dopo aver inizializzato il client SDK, puoi utilizzarlo per effettuare chiamate API per quel AWS servizio. Il codice di esempio richiama l'API Amazon S3 nel modo seguente:
const command = new PutObjectCommand({
Bucket: bucketName,
Key: key,
Body: receiptContent
});
Accesso alle variabili d'ambiente
Nel codice dell'handler, puoi fare riferimento a qualsiasi variabile di ambiente utilizzando il metodo process.env. In questo esempio, facciamo riferimento alla variabile di RECEIPT_BUCKET ambiente definita utilizzando la seguente riga di codice:
// Access environment variables const bucketName = process.env.RECEIPT_BUCKET; if (!bucketName) { throw new Error('RECEIPT_BUCKET environment variable is not set'); }
Utilizzo dello stato globale
Lambda esegue il codice statico e il costruttore della classe durante la fase di inizializzazione prima di richiamare la funzione per la prima volta. Le risorse create durante l'inizializzazione restano in memoria tra un'invocazione e l'altra, in modo da evitare di doverle creare ogni volta che si richiama una funzione.
Nell'esempio seguente, il codice di inizializzazione del client non rientra nel metodo del gestore principale. Il runtime inizializza il client prima che la funzione esegua il suo primo evento e il client resta disponibile per il riutilizzo in tutte le chiamate.
Best practice di codice per funzioni Lambda in Node.js
Segui queste linee guida quando crei funzioni Lambda:
-
Separare il gestore Lambda dalla logica principale. In questo modo è possibile creare una funzione di cui è più semplice eseguire l'unit test.
-
Controllare le dipendenze nel pacchetto di distribuzione della funzione. L'ambiente di esecuzione AWS Lambda contiene diverse librerie. Per i runtime Node.js e Python, questi includono gli SDK AWS. Per abilitare il set di caratteristiche e aggiornamenti della sicurezza più recenti, Lambda aggiorna periodicamente tali librerie. Tali aggiornamenti possono introdurre lievi modifiche al comportamento della funzione Lambda. Per mantenere il controllo completo delle dipendenze utilizzate dalla funzione, inserire tutte le dipendenze nel pacchetto di implementazione.
-
Ridurre la complessità delle dipendenze. Preferire framework più semplici che si caricano velocemente all'avvio del contesto di esecuzione.
-
Ridurre al minimo le dimensioni del pacchetto di implementazione al fine di soddisfare le esigenze di runtime. In questo modo viene ridotta la quantità di tempo necessaria per il download del pacchetto e per la relativa decompressione prima dell'invocazione.
Sfruttare il riutilizzo del contesto di esecuzione per migliorare le prestazioni della funzione. Inizializzare i client SDK e le connessioni al database all'esterno del gestore di funzioni e memorizzare localmente nella cache gli asset statici nella directory /tmp. Le chiamate successive elaborate dalla stessa istanza della funzione possono riutilizzare queste risorse. Ciò consente di risparmiare sui costi riducendo i tempi di esecuzione delle funzioni.
Per evitare potenziali perdite di dati tra le chiamate, non utilizzare il contesto di esecuzione per archiviare dati utente, eventi o altre informazioni con implicazioni di sicurezza. Se la funzione si basa su uno stato mutabile che non può essere archiviato in memoria all'interno del gestore, considerare la possibilità di creare una funzione separata o versioni separate di una funzione per ogni utente.
Utilizzare una direttiva keep-alive per mantenere le connessioni persistenti. Lambda elimina le connessioni inattive nel tempo. Se si tenta di riutilizzare una connessione inattiva quando si richiama una funzione, si verificherà un errore di connessione. Per mantenere la connessione persistente, utilizzare la direttiva keep-alive associata al runtime. Per un esempio, vedere Riutilizzo delle connessioni con Keep-Alive in Node.js.
Utilizzare le variabili di ambiente per passare i parametri operativi alla funzione. Se ad esempio si scrive in un bucket Amazon S3 anziché impostare come hard-coded il nome del bucket in cui si esegue la scrittura, configurare tale nome come una variabile di ambiente.
Evita di usare invocazioni ricorsive nella tua funzione Lambda, in cui la funzione si richiama da sola o avvia un processo che potrebbe richiamare nuovamente la funzione. Ciò potrebbe provocare un volume non desiderato di invocazioni della funzione e un aumento dei costi. Se noti un volume indesiderato di invocazioni, imposta immediatamente la simultaneità riservata della funzione su 0 per interrompere tutte le invocazioni della funzione mentre si aggiorna il codice.
Non utilizzare API non documentate e non pubbliche nel codice della funzione Lambda. Per i tempi di esecuzione gestiti AWS Lambda, Lambda applica periodicamente aggiornamenti di sicurezza e funzionalità alle API interne di Lambda. Questi aggiornamenti API interni potrebbero essere incompatibili con le versioni precedenti, causando conseguenze indesiderate come errori di chiamata se la funzione ha una dipendenza su queste API non pubbliche. Consulta il riferimento all'API per un elenco di API disponibili pubblicamente.
Scrivi un codice idempotente. La scrittura di un codice idempotente per le tue funzioni garantisce che gli eventi duplicati vengano gestiti allo stesso modo. Il tuo codice dovrebbe convalidare correttamente gli eventi e gestire con garbo gli eventi duplicati. Per ulteriori informazioni, consulta Come posso rendere idempotente la mia funzione Lambda?