Ciao a tutti, Jules Martin qui, di nuovo su agntmax.com!
Oggi voglio affrontare qualcosa che mi preoccupa, e probabilmente preoccupa molti di voi, da circa un anno: l’aumento dei costi dell’infrastruttura cloud, in particolare per quanto riguarda le funzioni serverless. Siamo stati tutti attratti dal sogno del “pagare per quello che usi”, e per molto tempo sembrava essere una realtà. Ma ultimamente ho visto le fatture salire, a volte in modo inspiegabile, anche quando i modelli di traffico sembravano stabili. È come se fossimo consumati dalla stessa flessibilità che avevamo adottato. Quindi, esploriamo qualcosa di molto specifico e attuale: Dominare il Mostro Serverless: Scoprire e Ridurre i Costi Nascosti di AWS Lambda.
Il mio personale percorso in questo campo è iniziato circa sei mesi fa. Abbiamo un microservizio centrale che gestisce l’autenticazione degli utenti e la gestione delle sessioni. È quasi interamente costruito su AWS Lambda, API Gateway, DynamoDB e Cognito. Per molto tempo, i costi erano perfettamente prevedibili. Poi, l’estate scorsa, la nostra fattura AWS per questo servizio specifico è aumentata di circa il 15%. Nessuna nuova funzionalità, nessun picco di traffico significativo. Inizialmente attribuii questo a una fluttuazione stagionale o a un piccolo bug che non avevo ancora trovato. Ma quando la fattura del mese successivo è arrivata ancora più alta, sapevo che dovevo approfondire. Non era solo un picco; era una tendenza e ci costava soldi veri.
L’Illusione dei Livelli “Gratuiti” e la Realtà delle Invocazioni “Minuscole”
Uno dei più grandi vantaggi del serverless, in particolare per le startup o i piccoli team, è il generoso livello gratuito. E lo è davvero! Un milione di invocazioni gratuite al mese per Lambda, oltre a una quantità significativa di tempo di calcolo. Il problema è che man mano che la tua applicazione cresce, queste invocazioni “gratuite” svaniscono più velocemente di una fetta di pizza durante un meetup tech. Spesso trascuriamo il volume totale di invocazioni minuscole, apparentemente insignificanti, che si accumulano. Pensa ai cron job, ai controlli di salute interni o persino ai meccanismi di retry provenienti da altri servizi. Ognuna di queste invocazioni conta.
La mia indagine sul nostro servizio di autenticazione ha rivelato esattamente questo. Avevamo una funzione Lambda, chiamiamola auth-token-refresher, progettata per aggiornare periodicamente i token di servizio interni. Era programmata per essere eseguita ogni cinque minuti. Sembra innocua, vero? 288 invocazioni al giorno. Moltiplica questo per 30 giorni e ottieni 8.640 invocazioni al mese. Aggiungi i nostri ambienti di sviluppo, staging e produzione, e improvvisamente rappresenta più di 25.000 invocazioni solo per un piccolo compito di manutenzione. Avevamo una dozzina di tali funzioni. All’improvviso, le nostre invocazioni “minuscole” non erano più così piccole.
Trovare i Colpevoli: Le Metriche CloudWatch Sono il Vostro Miglior Amico
Il primo passo per dominare questa bestia è sapere dove va il tuo denaro. AWS CloudWatch è indispensabile qui. Non limitarti a controllare il dashboard di fatturazione generale; esplora le metriche specifiche delle tue funzioni Lambda.
Ecco su cosa mi sono concentrato:
- Invocazioni: Questa è la metrica più semplice. Alti conteggi di invocazione per funzioni che non gestiscono il traffico utente diretto sono segnali di allerta immediati.
- Durata: Quanto dura ogni invocazione? Durate più lunghe significano costi di calcolo superiori.
- Utilizzo della Memoria: Stai sovraprovisionando memoria per le tue funzioni? Paga per quello che assegni, non per quello che utilizzi.
- Tassi di Errori: Tassi di errore elevati possono portare a retry, il che significa più invocazioni e cicli di calcolo sprecati.
Per il nostro auth-token-refresher, ho esaminato la sua metrica `Invocazioni`. In effetti, si eseguiva come un orologio, ogni cinque minuti. La durata era minima, solo circa 50 ms. Ma il volume enorme contribuiva al nostro costo totale di invocazione.
Esempio Pratico 1: Consolidare e Pianificare in Modo Più Intelligente
La soluzione per auth-token-refresher e diverse altre funzioni di manutenzione simili è stata sorprendentemente semplice: la consolidazione. Invece di avere funzioni Lambda singole attivate da eventi CloudWatch (o EventBridge oggigiorno) in orari separati, ho creato un’unica funzione Lambda “Maintenance Runner”.
Questo “Maintenance Runner” è attivato da una sola regola di evento CloudWatch, diciamo, una volta all’ora. All’interno di questo runner, ho un semplice dispatcher che controlla l’ora corrente ed esegue i compiti necessari. Per esempio:
import os
import datetime
def lambda_handler(event, context):
current_hour = datetime.datetime.now().hour
current_minute = datetime.datetime.now().minute
# Compito 1: Aggiornare il token di autenticazione (si eseguiva ogni 5 minuti)
if current_minute % 10 == 0: # Ora si esegue ogni 10 minuti
print("Esecuzione dell'aggiornamento del token di autenticazione...")
# Chiamare la logica reale di aggiornamento del token o un'altra funzione interna
refresh_auth_token()
# Compito 2: Pulire i vecchi log (si eseguiva ogni ora)
if current_hour % 1 == 0 and current_minute == 0: # Si esegue all'inizio dell'ora
print("Esecuzione della pulizia dei log...")
cleanup_old_logs()
# Compito 3: Controllare lo stato dei servizi esterni (si eseguiva ogni 30 minuti)
if current_minute == 0 or current_minute == 30:
print("Controllo dello stato dei servizi esterni...")
check_external_service()
return {
'statusCode': 200,
'body': 'Compiti di manutenzione eseguiti.'
}
def refresh_auth_token():
# ... logica reale di aggiornamento del token ...
pass
def cleanup_old_logs():
# ... logica reale di pulizia dei log ...
pass
def check_external_service():
# ... logica reale di controllo dei servizi esterni ...
pass
Questo semplice cambiamento ha immediatamente ridotto il numero di invocazioni per questi compiti di manutenzione da centinaia di migliaia al mese a qualche migliaio. I risparmi erano tangibili, non solo per quanto riguarda le invocazioni Lambda, ma anche per l’ingestione dei log CloudWatch e le chiamate all’API Gateway (se una di esse era esposta tramite API Gateway).
Il Rischio della Sovraprovisionamento di Memoria
Questo è un altro fattore di costo sottile che è spesso trascurato. Quando crei una funzione Lambda, assegni una certa quantità di memoria (ad esempio, 128 MB, 256 MB, 512 MB). Paga per questa memoria assegnata, indipendentemente da quanto utilizza effettivamente la tua funzione. Inoltre, la potenza della CPU cresce proporzionalmente all’allocazione della memoria. Quindi, se assegni 1 GB di memoria per un semplice script Python che ha bisogno solo di 128 MB, non stai solo pagando troppo per la memoria; stai anche pagando per cicli della CPU in più di cui non hai bisogno.
Ho imparato questo a mie spese con una funzione Lambda di elaborazione dati che era inizialmente configurata con 1 GB di memoria “per sicurezza”. Quando ho guardato le sue metriche CloudWatch per l’utilizzo della memoria, rimaneva sistematicamente al di sotto dei 200 MB, anche in periodi di carico elevato. Essenzialmente stavamo pagando per 800 MB di RAM inutilizzata e il relativo aumento della CPU.
Esempio Pratico 2: Ottimizzare l’Allocazione di Memoria con Lambda Power Tuning
Determinare manualmente l’impostazione di memoria ottimale può essere noioso. Devi distribuire, testare, monitorare, regolare e ripetere. Fortunatamente, esiste un ottimo strumento open-source chiamato AWS Lambda Power Tuning (sviluppato da Alex Casalboni presso AWS) che semplifica questo processo.
È un’applicazione serverless che ti aiuta a visualizzare e identificare l’impostazione di memoria ottimale per le tue funzioni Lambda in base ai costi e alle prestazioni. La distribuisci nel tuo account AWS, poi puoi usarla per testare le tue funzioni.
Ecco generalmente come funziona:
- Distribuisci lo strumento Power Tuning tramite il Serverless Application Repository o SAM.
- Invoca una macchina di stato (creata dallo strumento) con l’ARN della tua funzione Lambda e un payload.
- La macchina di stato invoca il tuo Lambda più volte con configurazioni di memoria varie (ad esempio, 128 MB, 256 MB, 512 MB, 1024 MB, ecc.).
- Analizza quindi i log di esecuzione e fornisce una visualizzazione che mostra i compromessi di costo e velocità per ciascuna impostazione di memoria.
Per la mia funzione Lambda di elaborazione dati, passando per il Power Tuner, ho scoperto che 256 MB era la scelta migliore in termini di costo, con una degradazione delle prestazioni trascurabile rispetto a 1 GB. Abbiamo immediatamente ridotto l’allocazione della memoria a 256 MB, il che ha comportato una riduzione del 75% dei costi di calcolo per questa funzione specifica. Non è stata un’eccezione isolata; da allora, ho preso l’abitudine di far passare le nuove funzioni o quelle riesaminate attraverso questo strumento.
Per utilizzarlo, dopo il deployment, di solito inizieresti la macchina a stati con qualcosa di simile (aggiustando l’ARN e il payload):
aws stepfunctions start-execution \
--state-machine-arn "arn:aws:states:REGIONE:ID_ACCOUNT:stateMachine:powerTuningStateMachine" \
--input '{ "lambdaARN": "arn:aws:lambda:REGIONE:ID_ACCOUNT:function:NOME_DELLA_TUA_FUNZIONE", "num": 100, "payload": {}, "parallel": 5 }'
L’output fornisce un grafico chiaro, mostrando esattamente dove i tuoi costi e la tua velocità si incrociano per prestazioni ottimali. È un cambiamento significativo per l’ottimizzazione dei costi.
Verbositá dei Log e Avvii a Freddo
Due altri ambiti che possono spesso sorprenderti sono la verbosità dei log e gli avvii a freddo. I log di CloudWatch non sono gratuiti. Ogni riga che la tua funzione Lambda stampa viene ingerita e memorizzata, e tu paghi per questo. Sebbene una buona registrazione sia cruciale per il debug, una registrazione eccessivamente verbosa (ad esempio, stampare oggetti interi o ripetere messaggi di stato inutilmente) può gonfiare rapidamente la tua fattura di CloudWatch Logs.
Ho trovato alcune funzioni che registravano l’intero corpo delle richieste HTTP a ogni invocazione. Sebbene fosse utile per lo sviluppo iniziale, in produzione, produceva solo rumore e costava denaro. Un rapido aggiustamento per registrare solo i metadati essenziali (ID della richiesta, codice di stato, punto d’accesso) ha ridotto significativamente la nostra ingestione di log.
Gli avvii a freddo, sebbene non rappresentino un “costo” diretto allo stesso modo, influenzano l’esperienza dell’utente e possono portare indirettamente a più tentativi o durate di fatturazione più lunghe se la tua funzione deve attendere risorse. Sebbene AWS abbia fatto progressi significativi nel ridurre i tempi di avvio a freddo, ottimizzare la dimensione del pacchetto della tua funzione e evitare una logica di inizializzazione complessa al di fuori del gestore può comunque fare la differenza. Per le funzioni critiche sensibili alla latenza, la concorrenza provisionata è un’opzione, ma tieni presente che paghi per questa concorrenza allocata anche quando è inattiva.
Esempio Pratico 3: Log Intelligenti e Variabili d’Ambiente
Per il logging, la soluzione più semplice è spesso la migliore. Utilizza variabili d’ambiente per controllare i livelli di registrazione. In Python, ad esempio, puoi fare così:
import os
import logging
LOG_LEVEL = os.environ.get('LOG_LEVEL', 'INFO').upper()
logging.basicConfig(level=LOG_LEVEL)
logger = logging.getLogger()
def lambda_handler(event, context):
logger.debug("Questo è un messaggio di debug, visibile solo se LOG_LEVEL è DEBUG")
logger.info("Elaborazione dell'evento: %s", event.get('request_id'))
try:
# ... logica della funzione ...
logger.debug("Elaborazione completata per request_id: %s", event.get('request_id'))
return {
'statusCode': 200,
'body': 'Successo'
}
except Exception as e:
logger.error("Errore durante l'elaborazione di request_id %s: %s", event.get('request_id'), str(e), exc_info=True)
return {
'statusCode': 500,
'body': 'Errore'
}
Impostando LOG_LEVEL su INFO in produzione e DEBUG in sviluppo/staging, puoi ridurre notevolmente la tua fattura di CloudWatch Logs senza sacrificare l’osservabilità quando ne hai bisogno.
Un altro consiglio è prestare attenzione a ciò che viene inizializzato al di fuori del gestore. Qualsiasi codice direttamente nell’ambito globale della tua funzione Lambda verrà eseguito durante l’avvio a freddo. Se hai operazioni costose come il pooling delle connessioni al database o grandi importazioni di librerie, considera di ritardarle fino a quando non sono realmente necessarie nel gestore, oppure assicurati che siano memorizzate efficientemente per le invocazioni calde successive.
Punti Chiave per la Tua Crociata sui Costi Serverless
D’accordo, abbiamo coperto parecchie cose. Ecco un riassunto dei passaggi pratici che puoi intraprendere da subito per iniziare a ridurre queste spese Lambda insidiose:
- Monitora incessantemente: Non limitarti a dare un’occhiata alla tua fattura AWS generale. Esplora le metriche di CloudWatch per le Invocazioni, la Durata e l’Utilizzo della Memoria per ogni funzione Lambda. Imposta allarmi per picchi inattesi.
- Consolida i compiti cron: Se hai più piccole funzioni Lambda programmate, considera di combinarle in un unico “Maintenance Runner” che smista i compiti secondo un programma meno frequente. Questo riduce significativamente il numero di invocazioni.
- Ottimizza l’allocazione della memoria: Utilizza strumenti come AWS Lambda Power Tuning per trovare la configurazione di memoria ottimale per le tue funzioni. Non fare supposizioni e non sovraprovisionare. Ricorda, più memoria significa più CPU, e paghi per entrambe.
- Controlla la verbosità dei log: Implementa livelli di registrazione guidati da variabili d’ambiente (ad esempio,
INFOper la produzione,DEBUGper lo sviluppo). Evita di registrare interi corpi di richiesta o stati interni eccessivi in produzione. La tua fattura di CloudWatch Logs ti ringrazierà. - Rivedi le funzioni non utilizzate: Audita periodicamente le tue funzioni Lambda. Ci sono funzioni obsolete, sperimentali o non più utilizzate ancora attive e generanti costi? Eliminale!
- Monitora la dimensione dei pacchetti: Pacchetti di distribuzione più piccoli significano avvii a freddo più rapidi e costi di archiviazione inferiori. Includi solo le dipendenze necessarie.
- Comprendi il tuo modello di prezzo: Rileggi la pagina dei prezzi di Lambda. Comprendi come vengono addebitate le invocazioni, i GB-secondi e il trasferimento dati. La conoscenza è potere, soprattutto quando si tratta del tuo portafoglio.
Domare il mostro serverless non significa evitare il serverless; si tratta di essere astuti e intenzionali nel modo in cui lo utilizziamo. La flessibilità e la scalabilità sono inestimabili, ma senza la giusta vigilanza, questi “piccoli” costi possono accumularsi per rappresentare una parte significativa del tuo budget. Vai avanti, monitora, ottimizza e risparmia!
Ecco, è tutto per me oggi. Fammi sapere nei commenti se hai altri trucchi o consigli per l’ottimizzazione dei costi Lambda!
🕒 Published:
Related Articles
- Trabajos de Ingeniero de IA: Dónde Encontrarlos, Cuánto Pagan y Cómo Conseguir Empleo
- Spedite più velocemente, non più difficile: Consigli per le prestazioni che evolvono realmente
- cultura delle performance degli agenti IA
- Expédiez plus vite, pas plus dur : Conseils de performance qui évoluent réellement