Il nome è fuorviante: anche con il serverless i server esistono, semplicemente non li vedi e non li gestisci. Il provider si occupa di macchine, sistemi operativi, aggiornamenti e scalabilità; tu fornisci solo il codice e paghi per il tempo in cui viene effettivamente eseguito. È un modello potente per alcuni casi e scomodo per altri, e conoscerne il funzionamento aiuta a capire da che parte sta il tuo progetto.
Il modello delle funzioni
La forma più nota di serverless è la funzione come servizio (Function as a Service). Scrivi una funzione, la carichi sulla piattaforma e la colleghi a un evento che la attiva:
- una richiesta HTTP a un certo indirizzo;
- un file caricato in un bucket di archiviazione;
- un messaggio arrivato in una coda;
- un orario pianificato, come ogni notte alle due;
- una modifica in un database.
Quando l'evento si verifica, la piattaforma avvia un ambiente di esecuzione, chiama la funzione e, dopo un po' di inattività, lo spegne. Se arrivano cento eventi insieme, avvia più ambienti in parallelo senza che tu debba fare nulla.
Il concetto di serverless è però più ampio delle funzioni. Comprende database che scalano da soli e fatturano per richiesta, code di messaggi gestite, servizi che eseguono container senza esporre server. Il filo comune è non dover dimensionare né gestire macchine.
I vantaggi
Si paga solo l'uso effettivo
Una funzione che non riceve richieste non costa nulla o quasi. Per servizi con traffico basso o irregolare, come un modulo di contatto, una conversione di immagini o un'automazione notturna, la spesa può essere molto inferiore a quella di un server sempre acceso.
Scalabilità automatica
Non serve prevedere i picchi: la piattaforma aumenta le esecuzioni parallele quando il carico cresce e le riduce quando cala.
Niente manutenzione dei server
Aggiornamenti del sistema operativo, correzioni di sicurezza delle macchine e sostituzione dell'hardware guasto sono a carico del provider. Resta tua la responsabilità del codice e delle sue dipendenze.
I limiti
L'avvio a freddo
Quando una funzione non viene usata da un po', il suo ambiente viene spento. La richiesta successiva deve aspettare che ne venga creato uno nuovo: è il cold start. Il ritardo va da poche decine di millisecondi a qualche secondo, a seconda del linguaggio, della dimensione del pacchetto e della piattaforma. Per un'elaborazione in background non conta; per un'API che deve rispondere sempre in fretta può essere un problema. Molte piattaforme permettono di tenere alcune istanze sempre pronte, ma a pagamento.
Limiti di esecuzione
Le funzioni hanno limiti su durata massima, memoria e dimensione delle richieste. Un'elaborazione che richiede mezz'ora va divisa in passi più piccoli o affidata a un altro tipo di servizio.
Assenza di stato
Ogni esecuzione può avvenire in un ambiente diverso, e nulla di ciò che resta in memoria o su disco è garantito per la volta successiva. Sessioni, file e dati vanno salvati in servizi esterni: database, cache, object storage.
Connessioni ai database
Cento funzioni avviate in parallelo possono aprire cento connessioni al database, superando i limiti di un database tradizionale. Servono un gestore di connessioni intermedio o database progettati per questo tipo di accesso.
Dipendenza dal fornitore
Il codice di una funzione è spesso semplice da spostare, ma tutto ciò che la circonda, cioè eventi, permessi, configurazioni, servizi collegati, è specifico della piattaforma. Migrare un'architettura serverless complessa da un provider all'altro richiede un lavoro considerevole.
Diagnosi più difficile
Un'applicazione divisa in decine di funzioni attivate da eventi è più difficile da seguire di un unico programma. Log centralizzati, tracce e identificativi di correlazione diventano indispensabili.
Quando i costi si ribaltano
Il prezzo a consumo è conveniente quando l'uso è basso o irregolare. Con un traffico alto e costante la situazione può invertirsi: un servizio che riceve richieste ininterrottamente, giorno e notte, può costare di più in funzioni che su un server dimensionato correttamente. Conviene fare il calcolo con i propri numeri, considerando anche le voci accessorie come gateway API, trasferimento dati e log.
Casi d'uso adatti e meno adatti
| Adatto | Meno adatto |
|---|---|
| Elaborazione di file caricati, come miniature o conversioni | Applicazioni con connessioni persistenti, come chat in tempo reale |
| Webhook e integrazioni tra servizi | Elaborazioni lunghe e continue |
| Automazioni pianificate | API con requisiti di latenza molto stringenti |
| API con traffico basso o molto variabile | Carichi alti e costanti nel tempo |
| Prototipi e progetti in fase iniziale | Sistemi che devono restare portabili tra fornitori |
Nel mio lavoro il serverless dà il meglio come «collante»: piccole funzioni che reagiscono a eventi e collegano servizi diversi, affiancate a un'applicazione principale che gira in modo più tradizionale.
In sintesi
- Serverless significa non gestire server: il provider si occupa di macchine e scalabilità, tu del codice.
- Le funzioni si attivano con eventi e si pagano solo per il tempo di esecuzione.
- I limiti principali sono avvio a freddo, durata massima, assenza di stato e connessioni ai database.
- Con traffico alto e costante un server tradizionale può costare meno.
- È ideale per automazioni, elaborazioni di file, webhook e servizi con uso irregolare.