Suggerimenti utili
Questo documento descrive le best practice per progettazione, implementazione, test e deployment di Cloud Functions.
Correttezza
Questa sezione descrive le best practice generali per la progettazione e l'implementazione di Cloud Functions.
Scrivi funzioni idempotenti
Le funzioni dovrebbero produrre lo stesso risultato anche se vengono chiamate più volte. Ciò ti consente di riprovare a eseguire una chiamata se la chiamata precedente non riesce parzialmente nel codice. Per maggiori informazioni, consulta la pagina relativa a come provare le funzioni basate su eventi.
Assicurati che le funzioni HTTP inviino una risposta HTTP
Se la funzione è attivata da HTTP, ricordati di inviare una risposta HTTP, come mostrato di seguito. In caso contrario, la funzione potrebbe essere eseguita fino al timeout. In questo caso, ti verrà addebitato l'intero tempo di timeout. I timeout possono anche causare comportamenti imprevedibili o avvii completi su chiamate successive, determinando un comportamento imprevedibile o una latenza aggiuntiva.
Node.js
Python
Go
Java
C#
Ruby
PHP
Non avviare le attività in background
Con attività in background si intende qualsiasi evento che si verifica dopo la fine della funzione.
La chiamata a una funzione termina quando la funzione restituisce o altrimenti segnala il completamento, ad esempio chiamando l'argomento callback
nelle funzioni basate su eventi Node.js. Qualsiasi codice eseguito dopo un'arresto controllato non può accedere alla CPU e non procederà.
Inoltre, quando viene eseguita una chiamata successiva nello stesso ambiente, l'attività in background riprende e interferisce con la nuova chiamata. Ciò potrebbe causare comportamenti imprevisti ed errori difficili da diagnosticare. L'accesso alla rete dopo la fine di una funzione di solito comporta il ripristino delle connessioni (codice di errore ECONNRESET
).
Spesso l'attività in background può essere rilevata nei log delle singole chiamate, trovando tutto ciò che viene registrato dopo la riga che indica che la chiamata è terminata. A volte l'attività in background può essere ulteriormente nascosta nel codice, soprattutto quando sono presenti operazioni asincrone come callback o timer. Controlla il codice per assicurarti che tutte le operazioni asincrone vengano completate prima di terminare la funzione.
Elimina sempre i file temporanei
L'archiviazione su disco locale nella directory temporanea è un file system in memoria. I file che scrivi consumano memoria disponibile per la tua funzione e talvolta rimangono tra le chiamate. La mancata eliminazione esplicita di questi file potrebbe causare un errore di memoria insufficiente e un avvio completo successivo.
Per vedere la memoria utilizzata da una singola funzione, selezionala nell'elenco di funzioni nella console Google Cloud e scegli il grafico Utilizzo memoria.
Non tentare di scrivere al di fuori della directory temporanea e assicurati di utilizzare metodi indipendenti dalla piattaforma o dal sistema operativo per creare percorsi di file.
Puoi ridurre i requisiti di memoria durante l'elaborazione di file di dimensioni maggiori utilizzando la pipeline. Ad esempio, puoi elaborare un file su Cloud Storage creando un flusso di lettura, passandolo attraverso un processo basato su flusso e scrivendo il flusso di output direttamente in Cloud Storage.
Strumenti
Questa sezione fornisce linee guida su come utilizzare gli strumenti per implementare, testare e interagire con Cloud Functions.
Sviluppo locale
Il deployment della funzione richiede un po' di tempo, quindi spesso è più veloce testare il codice della tua funzione localmente.
Error Reporting
Nelle lingue che utilizzano la gestione delle eccezioni, non inserire eccezioni non rilevate, in quanto forzano gli avvii completi nelle chiamate future. Per informazioni su come segnalare correttamente gli errori, consulta la guida a Error Reporting.
Non uscire manualmente
L'uscita manuale può causare comportamenti imprevisti. Usa invece le seguenti espressioni idiomatiche specifiche:
Node.js
Non usare process.exit()
. Le funzioni HTTP devono inviare una risposta con
res.status(200).send(message)
, mentre le funzioni basate su eventi verranno terminate quando vengono restituite (implicitamente o esplicitamente).
Python
Non usare sys.exit()
. Le funzioni HTTP devono restituire esplicitamente una risposta come stringa e le funzioni basate su eventi verranno terminate quando restituiscono un valore (implicitamente o esplicitamente).
Go
Non usare os.Exit()
. Le funzioni HTTP devono restituire esplicitamente una risposta come stringa e le funzioni basate su eventi verranno terminate quando restituiscono un valore (implicitamente o esplicitamente).
Java
Non usare System.exit()
. Le funzioni HTTP devono inviare una risposta con
response.getWriter().write(message)
, mentre le funzioni basate su eventi verranno terminate quando vengono restituite (implicitamente o esplicitamente).
C#
Non usare System.Environment.Exit()
. Le funzioni HTTP devono inviare una risposta con
context.Response.WriteAsync(message)
, mentre le funzioni basate su eventi verranno terminate quando vengono restituite (implicitamente o esplicitamente).
Ruby
Non utilizzare exit()
o abort()
. Le funzioni HTTP devono restituire esplicitamente una risposta come stringa e le funzioni basate su eventi verranno terminate quando restituiscono un valore (implicitamente o esplicitamente).
PHP
Non utilizzare exit()
o die()
. Le funzioni HTTP devono restituire esplicitamente una risposta come stringa e le funzioni basate su eventi verranno terminate quando restituiscono un valore (implicitamente o esplicitamente).
Utilizzare Sendgrid per inviare email
Cloud Functions non consente connessioni in uscita sulla porta 25, pertanto non puoi effettuare connessioni non sicure a un server SMTP. Il metodo consigliato per inviare email è utilizzare SendGrid. Puoi trovare altre opzioni per l'invio di email nel tutorial Invio di email da un'istanza per Google Compute Engine.
Prestazioni
Questa sezione descrive le best practice per ottimizzare il rendimento.
Usare le dipendenze in modo saggio
Poiché le funzioni sono stateless, l'ambiente di esecuzione viene spesso inizializzato da zero (durante un cosiddetto avvio a freddo). Quando si verifica un avvio completo, viene valutato il contesto globale della funzione.
Se le tue funzioni importano moduli, il tempo di caricamento per questi moduli può aumentare la latenza di chiamata durante un avvio completo. Puoi ridurre questa latenza e il tempo necessario per eseguire il deployment della funzione, caricando correttamente le dipendenze e non caricando le dipendenze non utilizzate dalla funzione.
Usa le variabili globali per riutilizzare gli oggetti nelle chiamate future
Non è garantito che lo stato di una funzione Cloud verrà preservato per le chiamate future. Tuttavia, Cloud Functions ricicla spesso l'ambiente di esecuzione di una chiamata precedente. Se dichiari una variabile nell'ambito globale, il suo valore può essere riutilizzato nelle chiamate successive senza dover essere ricalcolato.
In questo modo puoi memorizzare nella cache gli oggetti che possono essere costosi da ricreare in ogni chiamata della funzione. Lo spostamento di tali oggetti dal corpo della funzione all'ambito globale può comportare miglioramenti significativi delle prestazioni. L'esempio seguente crea un oggetto pesante solo una volta per istanza di funzione e lo condivide tra tutte le chiamate alle funzioni che raggiungono l'istanza specificata:
Node.js
Python
Go
Java
C#
Ruby
PHP
È particolarmente importante memorizzare nella cache le connessioni di rete, i riferimenti alle librerie e gli oggetti client API nell'ambito globale. Consulta la sezione Ottimizzazione del networking per esempi.
Eseguire l'inizializzazione lazy delle variabili globali
Se inizializza le variabili nell'ambito globale, il codice di inizializzazione verrà sempre eseguito tramite una chiamata di avvio completo, aumentando la latenza della funzione.
In alcuni casi, ciò causa timeout timeout per i servizi che vengono chiamati se non sono gestiti correttamente in un blocco try
/catch
. Se alcuni oggetti non vengono utilizzati in tutti i percorsi del codice, puoi inizializzarli lentamente on demand:
Node.js
Python
Go
Java
C#
Ruby
PHP
Le funzioni PHP non possono preservare le variabili tra richieste. L'ambito di esempio riportato sopra utilizza il caricamento lento per memorizzare nella cache i valori delle variabili globali in un file.
Ciò è particolarmente importante se definisci più funzioni in un singolo file, e funzioni diverse utilizzano variabili diverse. A meno che non utilizzi l'inizializzazione lazy, potresti sprecare risorse per le variabili inizializzate, ma mai utilizzate.
Riduci gli avvii completi impostando un numero minimo di istanze
Per impostazione predefinita, Cloud Functions scala il numero di istanze in base al numero di richieste in entrata. Puoi modificare questo comportamento predefinito impostando un numero minimo di istanze che Cloud Functions deve mantenere pronte per gestire le richieste. L'impostazione di un numero minimo di istanze riduce gli avvii completi dell'applicazione. Consigliamo di impostare un numero minimo di istanze se la tua applicazione è sensibile alla latenza.
Per scoprire come impostare un numero minimo di istanze, consulta Utilizzo di istanze minime.
Risorse aggiuntive
Scopri di più sull'ottimizzazione delle prestazioni nel video "Google Cloud Performance Atlas" Cloud Functions Cold Boot Time.