L'infrastruttura di Google è progettata per operare in modo elastico su larga scala: la maggior parte dei livelli può adattarsi alle maggiori richieste di traffico fino a raggiungere una scala enorme. Un pattern di progettazione fondamentale che lo rende possibile sono i livelli adattivi, ovvero componenti dell'infrastruttura che riassegnano dinamicamente il carico in base ai pattern di traffico. Questo adattamento, tuttavia, richiede tempo. Poiché Cloud Tasks consente di inviare volumi di traffico molto elevati, espone i rischi di produzione in situazioni in cui il traffico può aumentare più rapidamente di quanto l'infrastruttura possa adattarsi.
Panoramica
Questo documento fornisce linee guida sulle best practice per mantenere prestazioni elevate di Cloud Tasks
nelle code con traffico elevato. Una coda con TPS elevato è una coda con 500 attività create o
inviate al secondo (TPS) o più. Un gruppo di code con TPS elevato è un insieme contiguo di code, ad esempio [queue0001, queue0002, …, queue0099], in cui sono state create o inviate in totale almeno 2000 attività. Il TPS storico di una coda o di un gruppo di code è visualizzabile
utilizzando le metriche di Cloud Monitoring, api/request_count
per le operazioni "CreateTask" e queue/task_attempt_count
per i tentativi di attività. Le code e i gruppi di code con traffico elevato
sono soggetti a due diverse classi generali di errori:
Il sovraccarico della coda si verifica quando la creazione e l'invio di attività a una singola coda o a un gruppo di code aumentano più rapidamente di quanto l'infrastruttura delle code sia in grado di adattarsi. Analogamente, il sovraccarico del target si verifica quando la velocità con cui vengono inviati i task causa picchi di traffico nell'infrastruttura di destinazione downstream. In entrambi i casi, ti consigliamo di seguire un pattern 500/50/5: quando la scalabilità supera 500 TPS, aumenta il traffico di non più del 50% ogni 5 minuti. Questo documento esamina diversi scenari che possono introdurre rischi di scalabilità e fornisce esempi di come applicare questo pattern.
Sovraccarico della coda
Le code o i gruppi di code possono sovraccaricarsi in qualsiasi momento in caso di aumento improvviso del traffico. Di conseguenza, queste code possono riscontrare:
- Aumento della latenza di creazione delle attività
- Aumento del tasso di errori di creazione delle attività
- Frequenza di invio ridotta
Per difenderti da questo problema, ti consigliamo di stabilire controlli in qualsiasi situazione in cui la velocità di creazione o invio di una coda o di un gruppo di code può aumentare improvvisamente. Consigliamo un massimo di 500 operazioni al secondo per una coda o un gruppo di code inattivi, quindi di aumentare il traffico del 50% ogni 5 minuti. In teoria, puoi raggiungere 740.000 operazioni al secondo dopo 90 minuti utilizzando questa pianificazione dell'aumento. Ciò può verificarsi in diverse circostanze.
Ad esempio:
- Lancio di nuove funzionalità che utilizzano molto Cloud Tasks
- Spostamento del traffico tra le code
- Ribilanciamento del traffico su un numero maggiore o minore di code
- Esecuzione di job batch che inseriscono un numero elevato di attività
In questi casi e in altri, segui il pattern 500/50/5.
Utilizzo della suddivisione del traffico di App Engine
Se le attività vengono create da un'app App Engine, puoi sfruttare la suddivisione del traffico di App Engine (Standard/Flex) per attenuare gli aumenti di traffico. Suddividendo il traffico tra le versioni (Standard/Flex), le richieste che devono essere gestite in base alla frequenza possono essere aumentate nel tempo per proteggere l'integrità della coda. Ad esempio, considera il caso di aumento del traffico verso un gruppo di code appena espanso: siano [queue0000, queue0199] una sequenza di code con TPS elevato che ricevono un totale di 100.000 creazioni di TPS al picco.
Sia [queue0200, queue0399] una sequenza di nuove code. Dopo lo spostamento di tutto il traffico, il numero di code nella sequenza è raddoppiato e il nuovo intervallo di code riceve il 50% del traffico totale della sequenza.
Quando esegui il deployment della versione che aumenta il numero di code, incrementa gradualmente il traffico verso la nuova versione e quindi verso le nuove code utilizzando la suddivisione del traffico:
- Inizia a spostare l'1% del traffico sulla nuova release. Ad esempio,il 50% dell'1% di 100.000 TPS genera 500 TPS per l'insieme di nuove code.
- Ogni 5 minuti, aumenta del 50% il traffico inviato alla nuova release, come indicato nella tabella seguente:
Minuti dall'inizio del deployment | % del traffico totale spostato sulla nuova versione | % del traffico totale verso le nuove code | % del traffico totale verso le vecchie code |
---|---|---|---|
0 | 1.0 | 0,5 | 99,5 |
5 | 1,5 | 0,75 | 99,25 |
10 | 2.3 | 1,15 | 98,85 |
15 | 3.4 | 1,7 | 98,3 |
20 | 5.1 | 2,55 | 97,45 |
25 | 7,6 | 3,8 | 96,2 |
30 | 11.4 | 5.7 | 94,3 |
35 | 17.1 | 8,55 | 91,45 |
40 | 25,6 | 12.8 | 87,2 |
45 | 38,4 | 19.2 | 80,8 |
50 | 57,7 | 28,85 | 71,15 |
55 | 86,5 | 43.25 | 56,75 |
60 | 100 | 50 | 50 |
Picchi di traffico basati sulle uscite
Quando lanci una release che aumenta in modo significativo il traffico verso una coda o un gruppo di code, l'implementazione graduale è, ancora una volta, un meccanismo importante per attenuare gli aumenti. Esegui il rollout graduale delle tue istanze in modo che l'avvio iniziale non superi le 500 operazioni totali nelle nuove code, aumentando non più del 50% ogni 5 minuti.
Nuove code o gruppi di code con TPS elevato
Le code appena create sono particolarmente vulnerabili. I gruppi di code, ad esempio [queue0000, queue0001, …, queue0199], sono sensibili quanto le singole code durante le fasi iniziali di implementazione. Per queste code, l'implementazione graduale è una strategia importante. Avvia nuovi servizi o servizi aggiornati, che creano code o gruppi di code con un numero elevato di TPS, in modo che il carico iniziale sia inferiore a 500 TPS e gli incrementi del 50% o meno siano scaglionati a intervalli di almeno 5 minuti.
Gruppi di code appena espansi
Quando aumenti la capacità totale di un gruppo di code, ad esempio espandendo [queue0000-queue0199 a queue0000-queue0399], segui il pattern 500/50/5. È importante notare che, per le procedure di implementazione, i nuovi gruppi di code si comportano allo stesso modo delle singole code. Applica il pattern 500/50/5 al nuovo gruppo nel suo complesso, non solo alle singole code all'interno del gruppo. Per queste espansioni dei gruppi di code, l'implementazione graduale è ancora una strategia importante. Se la sorgente del traffico è App Engine, puoi utilizzare la suddivisione del traffico (vedi Picchi di traffico basati sulle release). Quando esegui la migrazione del servizio per aggiungere attività al numero maggiore di code, implementa gradualmente le istanze in modo che l'avvio iniziale non superi le 500 operazioni totali per le nuove code, aumentando non più del 50% ogni 5 minuti.
Espansione del gruppo di code di emergenza
A volte, potresti voler espandere un gruppo di code esistente, ad esempio perché è previsto che le attività vengano aggiunte al gruppo di code più rapidamente di quanto il gruppo possa distribuirle. Se i nomi delle nuove code sono distribuiti in modo uniforme tra i nomi delle code esistenti quando vengono ordinati in ordine lessicografico, il traffico può essere inviato immediatamente a queste code, a condizione che non ci siano più del 50% di nuove code interleaved e che il traffico verso ogni coda sia inferiore a 500 TPS. Questo metodo è un'alternativa all'utilizzo della divisione del traffico e dell'implementazione graduale, come descritto nelle sezioni precedenti.
Questo tipo di denominazione interleaved può essere ottenuto aggiungendo un suffisso alle code che terminano con numeri pari. Ad esempio, se hai 200 code esistenti [queue0000-queue0199] e vuoi creare 100 nuove code, scegli [queue0000a, queue0002a, queue0004a, …, queue0198a] come nuovi nomi delle code, anziché [queue0200-queue0299].
Se hai bisogno di un ulteriore aumento, puoi comunque alternare fino al 50% di code in più ogni 5 minuti.
Accodamento di attività su larga scala/batch
Quando è necessario aggiungere un numero elevato di attività, ad esempio milioni o miliardi, può essere utile un pattern di doppia iniezione. Anziché creare attività da un singolo job, utilizza una coda di inserimento. Ogni attività aggiunta alla coda dell'injector si espande e aggiunge 100 attività alla coda o al gruppo di code desiderato. La coda dell'injector può essere accelerata nel tempo, ad esempio inizia a 5 TPS, poi aumenta del 50% ogni 5 minuti.
Attività con nome
Quando crei una nuova attività, Cloud Tasks le assegna un nome univoco per impostazione predefinita. Puoi assegnare il tuo nome a un'attività utilizzando il parametro name. Tuttavia, ciò introduce un overhead delle prestazioni significativo, con conseguente aumento delle latenze e potenzialmente dei tassi di errore associati alle attività denominate. Questi costi possono aumentare in modo significativo se le attività vengono denominate in sequenza, ad esempio con i timestamp. Pertanto, se assegni i tuoi nomi, ti consigliamo di utilizzare un prefisso ben distribuito per i nomi delle attività, ad esempio un hash dei contenuti. Consulta la documentazione per ulteriori dettagli sull'assegnazione di un nome a un'attività.
Sovraccarico del target
Cloud Tasks può sovraccaricare altri servizi che utilizzi, come App Engine, Datastore e l'utilizzo della rete, se gli invii da una coda aumentano drasticamente in un breve periodo di tempo. Se si è accumulato un backlog di attività, la riattivazione di queste code può potenzialmente sovraccaricare questi servizi. La difesa consigliata è lo stesso pattern 500/50/5 suggerito per il sovraccarico della coda: se una coda invia più di 500 TPS, aumenta il traffico attivato da una coda di non più del 50% ogni 5 minuti. Per monitorare in modo proattivo gli aumenti del traffico, utilizza le metriche di Cloud Monitoring. Puoi utilizzare gli avvisi di Cloud Monitoring per rilevare situazioni potenzialmente pericolose.
Rianimazione o ripresa delle code ad alto TPS
Quando una coda o una serie di code viene riattivata o riabilitata, le code riprendono
l'invio. Se la coda ha molte attività, la velocità di distribuzione della coda appena attivata
potrebbe aumentare notevolmente da 0 TPS alla capacità massima della coda. Per
aumentare gradualmente, scaglionare la ripresa delle code o controllare le velocità di distribuzione delle code utilizzando maxDispatchesPerSecond
di Cloud Tasks.
Attività pianificate collettive
Un numero elevato di attività, la cui esecuzione è pianificata contemporaneamente, può anche introdurre un rischio di sovraccarico della destinazione. Se devi avviare un numero elevato di attività contemporaneamente, valuta la possibilità di utilizzare i controlli della frequenza della coda per aumentare gradualmente la frequenza di distribuzione o aumentare esplicitamente la capacità target in anticipo.
Aumento del fan-out
Quando aggiorni i servizi eseguiti tramite Cloud Tasks, l'aumento del numero di chiamate remote può creare rischi di produzione. Ad esempio, supponiamo che le attività in una coda con TPS elevato chiamino il gestore /task-foo
. Una nuova release potrebbe aumentare significativamente il costo della chiamata /task-foo
se, ad esempio, aggiunge diversi costosi chiamate Datastore al gestore. Il risultato netto di un rilascio di questo tipo sarebbe un aumento massiccio del traffico di Datastore immediatamente correlato alle variazioni del traffico degli utenti. Utilizza il rilascio graduale o la suddivisione del traffico per gestire l'aumento.
Nuovi tentativi
Il codice può riprovare in caso di errore durante l'esecuzione di chiamate all'API Cloud Tasks. Tuttavia, quando una parte significativa delle richieste non va a buon fine a causa di errori lato server, un alto tasso di tentativi può sovraccaricare ulteriormente le code e causare un recupero più lento. Pertanto, ti consigliamo di limitare la quantità di traffico in uscita se il client rileva che una parte significativa delle richieste non va a buon fine a causa di errori lato server, ad esempio utilizzando l'algoritmo di limitazione adattiva descritto nel capitolo Gestione del sovraccarico del libro Site Reliability Engineering. Le librerie client gRPC di Google implementano una variante di questo algoritmo.