Ambiente di esecuzione di Cloud Functions
Le funzioni Cloud Run vengono eseguite in un ambiente serverless completamente gestito in cui Google gestisce infrastruttura, sistemi operativi e ambienti di runtime. Ogni funzione viene eseguita nel proprio contesto di esecuzione sicuro isolato, viene scalata automaticamente e ha un ciclo di vita indipendente dalle altre funzioni.
Runtime
Cloud Run Functions supporta più runtime di linguaggi. Ciascuna contiene un set standard di pacchetti di sistema, nonché gli strumenti e le librerie necessari per quella lingua. Avrai bisogno del valore ID runtime se esegui il deployment delle funzioni dalla riga di comando o tramite Terraform.
Gli aggiornamenti di sicurezza e manutenzione vengono resi disponibili per tutti gli ambienti di esecuzione di prima e 2ª generazione. Questi aggiornamenti vengono applicati automaticamente o manualmente, a seconda dell'ambiente e di come è stato configurato. Per ulteriori informazioni sugli aggiornamenti dell'ambiente di esecuzione, consulta Proteggere la funzione Cloud Run.
Node.js
Python
Runtime | Generazione | Ambiente | ID runtime | Immagine runtime |
---|---|---|---|---|
Python 3.13 | 2ª gen. | Ubuntu 22.04 | python313 | us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python313 |
Python 3.12 | 1ª gen., 2ª gen. | Ubuntu 22.04 | python312 | us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python312 |
Python 3.11 | 1ª gen., 2ª gen. | Ubuntu 22.04 | python311 | us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python311 |
Python 3.10 | 1ª gen., 2ª gen. | Ubuntu 22.04 | python310 | us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python310 |
Python 3.9 | 1ª gen., 2ª gen. | Ubuntu 18.04 | python39 | us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/python39 |
Python 3.8 | 1ª gen., 2ª gen. | Ubuntu 18.04 | python38 | us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/python38 |
Python 3.7 | 1ª gen. | Ubuntu 18.04 | python37 | us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/python37 |
Vai
Java
Runtime | Generazione | Ambiente | ID runtime | Immagine runtime |
---|---|---|---|---|
Java 21 | 2ª gen. | Ubuntu 22.04 | java21 | us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/java21 |
Java 17 | 1ª gen., 2ª gen. | Ubuntu 22.04 | java17 | us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/java17 |
Java 11 | 1ª gen., 2ª gen. | Ubuntu 18.04 | java11 | us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/java11 |
Ruby
Runtime | Generazione | Ambiente | ID runtime | Immagine runtime |
---|---|---|---|---|
Ruby 3.4 | 2ª gen. | Ubuntu 22.04 | ruby34 | us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/ruby34 |
Ruby 3.3 | 1ª gen., 2ª gen. | Ubuntu 22.04 | ruby33 | us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/ruby33 |
Ruby 3.2 | 1ª gen., 2ª gen. | Ubuntu 22.04 | ruby32 | us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/ruby32 |
Ruby 3.0 | 1ª gen., 2ª gen. | Ubuntu 18.04 | ruby30 | us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/ruby30 |
Ruby 2.7 | 1ª gen., 2ª gen. | Ubuntu 18.04 | ruby27 | us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/ruby27 |
Ruby 2.6 | 1ª gen., 2ª gen. | Ubuntu 18.04 | ruby26 | us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/ruby26 |
PHP
Runtime | Ambiente | Generazione | ID runtime | Immagine runtime |
---|---|---|---|---|
PHP 8.4 | 2ª gen. | Ubuntu 22.04 | php84 | us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/php84 |
PHP 8.3 | 2ª gen. | Ubuntu 22.04 | php83 | us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/php83 |
PHP 8.2 | 1ª gen., 2ª gen. | Ubuntu 22.04 | php82 | us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/php82 |
PHP 8.1 | 1ª gen., 2ª gen. | Ubuntu 18.04 | php81 | us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/php81 |
PHP 7.4 | 1ª gen., 2ª gen. | Ubuntu 18.04 | php74 | us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/php74 |
.NET Core
Runtime | Generazione | Ambiente | ID runtime | Immagine runtime |
---|---|---|---|---|
.NET Core 8 | 2ª gen. | Ubuntu 22.04 | dotnet8 | us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/dotnet8 |
.NET Core 6 | 1ª gen., 2ª gen. | Ubuntu 22.04 | dotnet6 | us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/dotnet6 |
.NET Core 3 | 1ª gen., 2ª gen. | Ubuntu 18.04 | dotnet3 | us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/dotnet3 |
Comportamento della scalabilità automatica
Cloud Run Functions implementa il paradigma serverless, in cui esegui il tuo codice senza preoccuparti dell'infrastruttura sottostante, come server o macchine virtuali. Una volta eseguito il deployment, le funzioni vengono gestite e scalate automaticamente.
Cloud Run Functions gestisce le richieste in entrata assegnandole alle istanze della funzione. A seconda del volume di richieste e del numero di istanze di funzioni esistenti, le funzioni Cloud Run possono assegnare una richiesta a un'istanza esistente o crearne una nuova.
Nei casi in cui il volume delle richieste in entrata supera il numero di istanze esistenti, le funzioni Cloud Run potrebbero avviare più nuove istanze per gestire le richieste. Questo comportamento di scalabilità automatica consente alle funzioni Cloud Run di gestire molte richieste in parallelo, ognuna utilizzando un'istanza diversa della funzione.
In alcuni casi, lo scaling illimitato potrebbe non essere auspicabile. Per risolvere questo problema, Cloud Run Functions consente di configurare un numero massimo di istanze che possono coesistere in un determinato momento per una particolare funzione.
Condizione stateless
Per abilitare la gestione e la scalabilità automatiche delle funzioni, queste devono essere senza stato: l'invocazione di una funzione non deve basarsi sullo stato in memoria impostato da un'invocazione precedente. Le chiamate potrebbero essere gestite da istanze di funzioni diverse, che non condividono variabili globali, memoria, file system o altro stato.
Se devi condividere lo stato tra le chiamate di funzioni, la tua funzione deve utilizzare un servizio come Memorystore, Datastore, Firestore o Cloud Storage per rendere persistenti i dati. Per saperne di più su database e opzioni di archiviazione forniti da Google Cloud, consulta Google Cloud database e Google Cloud prodotti di archiviazione.
Contemporaneità
Cloud Run Functions (2ª generazione.)
Cloud Run (2ª generazione) supporta la gestione di più richieste simultanee su una singola istanza di funzione. Ciò può essere utile per evitare avvii a freddo, poiché un'istanza già riscaldata può elaborare più richieste contemporaneamente, riducendo così la latenza complessiva. Per maggiori dettagli, vedi Concorrenza.
Cloud Run Functions (1ª generazione.)
Nelle funzioni Cloud Run (1ª generazione.), ogni istanza di una funzione gestisce una sola richiesta in parallelo alla volta. Ciò significa che mentre il codice elabora una richiesta, non è possibile che una seconda richiesta venga indirizzata alla stessa istanza. Pertanto, la richiesta originale può utilizzare l'intera quantità di risorse (memoria e CPU) che allochi.
Poiché le richieste simultanee nelle funzioni Cloud Run (1ª generazione.) vengono elaborate da diverse istanze di funzione, non condividono variabili o memoria locale. Per saperne di più, consulta Assenza di stato e Durata dell'istanza della funzione.
Avvii a freddo
Una nuova istanza di funzione viene avviata in due casi:
Quando esegui il deployment della funzione.
Quando viene creata automaticamente una nuova istanza di funzione per scalare in base al carico o occasionalmente per sostituire un'istanza esistente.
L'avvio di una nuova istanza di funzione comporta il caricamento del runtime e del codice. Le richieste che includono l'avvio dell'istanza della funzione, chiamate avvii a freddo, possono essere più lente delle richieste indirizzate alle istanze della funzione esistenti. Se la funzione riceve un carico costante, il numero di avvii a freddo è in genere trascurabile, a meno che la funzione non si arresti in modo anomalo di frequente e richieda il riavvio dell'ambiente della funzione.
Se il codice della funzione genera un'eccezione non rilevata o arresta in modo anomalo il processo corrente, l'istanza della funzione potrebbe essere riavviata. Ciò può comportare più avvii a freddo, con conseguente aumento della latenza, pertanto ti consigliamo di rilevare le eccezioni ed evitare in altro modo la terminazione del processo corrente.
Se la tua funzione è sensibile alla latenza, valuta la possibilità di impostare un numero minimo di istanze per evitare gli avvii a freddo.
Durata dell'istanza di funzione
Le istanze di funzione sono in genere resilienti e riutilizzate dalle invocazioni di funzione successive, a meno che il numero di istanze non venga ridotto a causa della mancanza di traffico continuo o dell'arresto anomalo della funzione. Ciò significa che quando termina l'esecuzione di una funzione, un'altra chiamata di funzione può essere gestita dalla stessa istanza di funzione.
Ambito della funzione rispetto all'ambito globale
Una singola chiamata di funzione comporta l'esecuzione solo del corpo della funzione dichiarata come punto di ingresso. L'ambito globale del codice sorgente della funzione viene eseguito solo sugli avvii a freddo e non sulle istanze già inizializzate.
Node.js
Python
Go
Java
Ruby
Puoi utilizzare le variabili globali come ottimizzazione del rendimento, ma non devi fare affidamento sullo stato impostato nell'ambito globale dalle chiamate di funzione precedenti. Per ulteriori informazioni, consulta la sezione Assenza di stato.
Puoi presupporre che per ogni istanza di funzione, l'ambito globale sia stato eseguito esattamente una volta prima che venga richiamato il codice della funzione. Tuttavia, non devi fare affidamento sul numero totale o sulla tempistica delle esecuzioni dell'ambito globale, in quanto potrebbero variare a seconda dell'attività di scalabilità automatica.
Cronologia di esecuzione della funzione
Una funzione ha accesso alle risorse allocate (memoria e CPU) solo per la durata dell'esecuzione della funzione. L'esecuzione del codice al di fuori del periodo di esecuzione non è garantita e può essere interrotta in qualsiasi momento. Pertanto, devi sempre segnalare correttamente la fine dell'esecuzione della funzione ed evitare di eseguire qualsiasi codice oltre questo punto. Per indicazioni, consulta Funzioni HTTP, Funzioni in background e Funzioni CloudEvent.
L'esecuzione della funzione è soggetta anche alla durata del timeout della funzione. Per saperne di più, consulta Timeout della funzione.
Tieni conto della sequenza temporale di esecuzione quando inizializzi l'applicazione. Le attività in background non devono essere create nell'ambito globale durante l'inizializzazione, in quanto verrebbero eseguite al di fuori della durata di una richiesta.
Garanzie di esecuzione
Le funzioni vengono in genere richiamate una volta per ogni evento in entrata. Tuttavia, Cloud Run Functions non garantisce una singola chiamata in tutti i casi a causa delle differenze negli scenari di errore.
Il numero massimo o minimo di volte in cui la funzione può essere chiamata per un singolo evento dipende dal tipo di funzione:
Le funzioni HTTP vengono richiamate al massimo una volta. Ciò è dovuto alla natura sincrona delle chiamate HTTP e significa che qualsiasi errore che si verifica durante l'invocazione della funzione verrà restituito senza essere ritentato. Il chiamante di una funzione HTTP deve gestire gli errori e riprovare se necessario.
Le funzioni basate su eventi vengono richiamate almeno una volta. Ciò è dovuto alla natura asincrona degli eventi, in cui non esiste un chiamante che attende la risposta. In rare circostanze, il sistema potrebbe richiamare una funzione basata su eventi più di una volta per garantire la consegna dell'evento. Se la chiamata di una funzione basata su eventi non va a buon fine e restituisce un errore, la funzione non verrà chiamata di nuovo a meno che non siano abilitati i nuovi tentativi in caso di errore per quella funzione.
Per assicurarti che la funzione si comporti correttamente nei tentativi di esecuzione ripetuti, devi renderla idempotente implementandola in modo che i risultati desiderati (e gli effetti collaterali) vengano prodotti anche se un evento viene inviato più volte. Nel caso delle funzioni HTTP, ciò significa anche restituire il valore desiderato anche se il chiamante riprova le chiamate all'endpoint della funzione HTTP. Per saperne di più su come rendere idempotente la tua funzione, consulta Nuovo tentativo per le funzioni basate su eventi.
Memoria e file system
A ogni funzione viene allocata una determinata quantità di memoria per il suo utilizzo. Puoi configurare la quantità di memoria al momento del deployment. Per ulteriori informazioni, consulta Configurare la memoria.
L'ambiente di esecuzione della funzione include un file system in memoria che contiene i file di origine e le directory di cui è stato eseguito il deployment con la funzione (vedi Strutturare il codice sorgente). La directory contenente i file di origine è di sola lettura, ma il resto del file system è scrivibile (ad eccezione dei file utilizzati dal sistema operativo). L'utilizzo del file system viene conteggiato ai fini dell'utilizzo della memoria di una funzione.
La funzione può interagire con il file system utilizzando i metodi standard in ogni linguaggio di programmazione.
Rete
La tua funzione può accedere a internet pubblico utilizzando metodi standard in ogni linguaggio di programmazione, tramite librerie integrate offerte dal runtime o librerie di terze parti incluse come dipendenze.
Prova a riutilizzare le connessioni di rete tra le chiamate di funzioni. Tieni presente, tuttavia, che una connessione che rimane inutilizzata per 10 minuti potrebbe essere chiusa dal sistema e ulteriori tentativi di utilizzare una connessione chiusa restituiranno un errore "connection reset". Il codice deve utilizzare una libreria che gestisca bene le connessioni chiuse oppure gestirle in modo esplicito se utilizza costrutti di rete di basso livello.
Isolamento delle funzioni
Ogni funzione di cui è stato eseguito il deployment è isolata da tutte le altre funzioni, anche da quelle di cui è stato eseguito il deployment dallo stesso file di origine. In particolare, non condividono memoria, variabili globali, file system o altro stato.
Per condividere i dati tra le funzioni di cui è stato eseguito il deployment, puoi utilizzare servizi come Memorystore, Datastore, Firestore o Cloud Storage. In alternativa, puoi richiamare una funzione da un'altra utilizzando i trigger appropriati e trasmettendo i dati necessari. Ad esempio, invia una richiesta HTTP all'endpoint di una funzione HTTP o pubblica un messaggio in un argomento Pub/Sub per attivare una funzione Pub/Sub.