Risolvere i problemi di latenza elevata nelle app App Engine

In molti casi, la latenza elevata nell'applicazione si traduce in errori del server 5xx. Poiché la causa principale sia dell'errore sia degli picchi di latenza potrebbe essere la stessa, applica le seguenti strategie per la risoluzione dei problemi di latenza:

  1. Definire l'ambito del problema di latenza
  2. Identifica la causa
  3. Risolvere i problemi

Definisci l'ambito del problema di latenza

Definisci l'ambito del problema ponendoti le seguenti domande:

  • Quali applicazioni, servizi e versioni sono interessate da questo problema?
  • Quali endpoint specifici del servizio sono interessati da questo problema?
  • Questo problema riguarda tutti i clienti a livello globale o un sottoinsieme specifico di clienti?
  • Quali sono l'ora di inizio e di fine dell'incidente? Valuta la possibilità di specificare il fuso orario.
  • Quali sono gli errori specifici?
  • Che cos'è il delta di latenza osservato, che in genere viene specificato come aumento in un percentile specifico? Ad esempio, la latenza è aumentata di 2 secondi al 90° percentile.
  • Come hai misurato la latenza? In particolare, l'hai misurato sul client o è visibile in Cloud Logging o nei dati sulla latenza di Cloud Monitoring forniti dall'infrastruttura di servizio App Engine?
  • Quali sono le dipendenze del tuo servizio e ce ne sono alcune che registrano incidenti?
  • Di recente hai apportato modifiche al codice, alla configurazione o al carico di lavoro che hanno attivato questo problema?

Un servizio potrebbe avere il proprio monitoraggio e logging personalizzati che puoi utilizzare per restringere ulteriormente l'ambito del problema. Definire l'ambito del problema ti aiuterà a individuare la probabile causa principale e a determinare i passaggi successivi per la risoluzione dei problemi.

Identificare la causa

Determina quale componente nel percorso della richiesta è più probabile che causi la latenza o gli errori. I componenti principali nel percorso della richiesta sono i seguenti:

Client --> internet --> Google Front End (GFE) (GFE) --> infrastruttura di servizio App Engine --> istanza di servizio

Se le informazioni precedenti non indicano la causa dell'errore, applica le seguenti strategie durante la revisione dell'integrità e del rendimento dell'istanza di servizio:

  1. Monitora i log delle richieste di App Engine. Se in questi log vengono visualizzati errori di codice stato HTTP o una latenza elevata, il problema probabilmente riguarda l'istanza che esegue il servizio.

  2. Se il numero di istanze di servizio non è stato aumentato in base ai livelli di traffico, le istanze potrebbero essere sovraccaricate, con conseguente aumento degli errori e della latenza.

  3. Se noti errori o latenze elevati in Cloud Monitoring, il problema potrebbe riguardare l'upstream del bilanciatore del carico, che registra le metriche di App Engine. Nella maggior parte dei casi, questo indica un problema nelle istanze di servizio.

  4. Se noti una latenza elevata o errori nelle metriche di monitoraggio, ma non nei log delle richieste, significa che si è verificato un errore di bilanciamento del carico o un errore grave dell'istanza che impedisce al bilanciatore del carico di instradare le richieste. Per distinguere questi casi, esamina i log delle richieste prima dell'inizio dell'incidente. Se i log delle richieste mostrano una latenza crescente prima dell'errore, le istanze dell'applicazione hanno iniziato a non rispondere prima che il bilanciatore del carico smettesse di inoltrarvi le richieste.

Risoluzione dei problemi

Questa sezione descrive le strategie di risoluzione dei problemi di latenza elevata da parte dei seguenti componenti nel percorso della richiesta:

  1. Internet
  2. Google Front End (GFE)
  3. Infrastruttura di pubblicazione di App Engine
  4. Istanze dell'applicazione
  5. Dipendenze dell'applicazione

Internet

La tua applicazione potrebbe riscontrare problemi di latenza a causa di una scarsa connettività o di una larghezza di banda ridotta.

Connettività a internet scadente

Per determinare se il problema è la scarsa connettività a internet, esegui il seguente comando sul client:

$ curl -s -o /dev/null -w '%{time_connect}\n' <hostname>

Il valore di time_connect rappresenta la latenza della connessione del client al Front-end Google più vicino. Per le connessioni lente, esegui ulteriori operazioni di risoluzione dei problemi utilizzando traceroute per determinare quale hop sulla rete causa il ritardo.

Esegui test da client in diverse località geografiche. App Engine indirizza automaticamente le richieste al data center Google più vicino, che varia in base alla località del cliente.

Larghezza di banda insufficiente

L'applicazione potrebbe rispondere rapidamente, ma i colli di bottiglia della rete ritardano l'invio rapido dei pacchetti sulla rete da parte dell'infrastruttura di servizio App Engine, rallentando le risposte.

Google Front End (GFE)

L'applicazione potrebbe riscontrare problemi di latenza a causa di routing errato, richieste parallele inviate da client HTTP/2 o interruzione delle connessioni SSL.

Mappare un indirizzo IP del client a una regione geografica

Google risolve il nome host dell'applicazione App Engine nel GFE più vicino al client in base all'indirizzo IP del client utilizzato nella ricerca DNS. Se il resolver DNS del client non utilizza il protocollo EDNS0, Google potrebbe non inoltrare le richieste del client al GFE più vicino.

Blocco head-of-line HTTP/2

I client HTTP/2 che inviano più richieste in parallelo potrebbero riscontrare una latenza elevata a causa del blocco all'inizio della coda nella GFE. Per risolvere il problema, i client devono utilizzare il protocollo QUIC.

Terminazione SSL per i domini personalizzati

Il GFE potrebbe terminare la connessione SSL. Se utilizzi un dominio personalizzato anziché un dominio appspot.com, la terminazione SSL richiede un hop aggiuntivo. Ciò potrebbe comportare un aumento della latenza per le applicazioni in esecuzione in alcune regioni. Per maggiori informazioni, consulta Mappatura di domini personalizzati.

Infrastruttura di pubblicazione di App Engine

Potresti notare una latenza elevata nella tua applicazione a causa di incidenti a livello di servizio o di scalabilità automatica.

Incidenti a livello di servizio

Google pubblica i dettagli di un problema grave a livello di servizio nella dashboard Integrità del servizio. Tuttavia, Google esegue le implementazioni gradualmente, pertanto è improbabile che un incidente a livello di servizio influisca su tutte le istanze contemporaneamente.

Scalabilità automatica

La latenza elevata o gli errori possono derivare dai seguenti scenari di scalabilità automatica:

  • Eseguire lo scale up del traffico troppo rapidamente: la scalabilità automatica di App Engine potrebbe non scalare le tue istanze alla stessa velocità con cui aumenta il traffico, causando un sovraccarico temporaneo. In genere, il sovraccarico si verifica quando il traffico viene generato da un programma informatico anziché dagli utenti finali. Per risolvere il problema, riduci la velocità del sistema che genera il traffico.

  • Picchi di traffico: i picchi di traffico potrebbero causare una latenza elevata nei casi in cui un servizio con scalabilità automatica debba scalare più rapidamente di quanto sia possibile, senza influire sulla latenza. Il traffico degli utenti finali in genere non causa picchi di traffico frequenti. Se noti picchi di traffico, devi esaminarne la causa. Se un sistema batch viene eseguito a intervalli, potresti essere in grado di uniformare il traffico o utilizzare impostazioni di scalabilità diverse.

  • Impostazioni del gestore della scalabilità automatica: il gestore della scalabilità automatica può essere configurato in base alle caratteristiche di scalabilità del servizio. I parametri di scalabilità potrebbero diventare non ottimali nei seguenti scenari:

    • Le impostazioni di scalabilità dell'ambiente standard di App Engine potrebbero causare latenza se impostate in modo troppo aggressivo. Se nei log visualizzi le risposte del server con il codice di stato 500 e il messaggio "La richiesta è stata interrotta dopo aver atteso troppo tempo per tentare di soddisfare la richiesta", significa che la richiesta ha superato il tempo di attesa nella coda in attesa mentre aspettava un'istanza inattiva.

    • Potresti notare un aumento del tempo in attesa con il ridimensionamento manuale anche se hai eseguito il provisioning di istanze sufficienti. Ti consigliamo di non utilizzare la scalabilità manuale se la tua applicazione gestisce il traffico degli utenti finali. La scalabilità manuale è più adatta per i carichi di lavoro come le code di attività.

    • La scalabilità di base riduce al minimo i costi a spese della latenza. Ti consigliamo di non utilizzare la scalabilità di base per i servizi sensibili alla latenza.

    • L'impostazione di scalabilità predefinita di App Engine offre una latenza ottimale per la maggior parte dei servizi. Se continui a visualizzare richieste con tempi di attesa elevati, specifica un numero minimo di istanze. Se ottimizzi le impostazioni di scalabilità per ridurre i costi riducendo al minimo le istanze inattive, rischi picchi di latenza se il carico aumenta improvvisamente.

Ti consigliamo di eseguire un benchmark del rendimento con le impostazioni di scalabilità predefinite, quindi di eseguire un nuovo benchmark dopo ogni modifica di queste impostazioni.

Deployment

Una latenza elevata poco dopo un deployment indica che non hai eseguito un adeguato scaling prima di eseguire la migrazione del traffico. Le istanze più recenti potrebbero non aver preriscaldato le cache locali e vengono pubblicate più lentamente rispetto alle istanze precedenti.

Per evitare picchi di latenza, non eseguire il deployment di un servizio App Engine utilizzando lo stesso nome della versione di una versione esistente del servizio. Se riutilizzi il nome di una versione esistente, non potrai eseguire la migrazione graduale del traffico alla nuova versione. Le richieste potrebbero essere più lente perché App Engine riavvia ogni istanza in un breve periodo di tempo. Devi anche eseguire nuovamente il deployment se vuoi ripristinare la versione precedente.

Istanza dell'applicazione

Questa sezione descrive le strategie comuni che puoi applicare alle istanze e al codice sorgente dell'applicazione per ottimizzare le prestazioni e ridurre la latenza.

Codice dell'applicazione

I problemi nel codice dell'applicazione possono essere difficili da eseguire il debug, soprattutto se sono intermittenti o non riproducibili.

Per risolvere i problemi:

  • Per diagnosticare i problemi, ti consigliamo di eseguire l'instrumentazione dell'applicazione utilizzando il logging, il monitoraggio e il tracciamento. Puoi anche utilizzare Cloud Profiler.

  • Prova a riprodurre il problema in un ambiente di sviluppo locale, che potrebbe consentirti di eseguire strumenti di debug specifici per il linguaggio che potrebbero non essere possibili da eseguire in App Engine.

  • Per comprendere meglio in che modo l'applicazione non funziona e quali colli di bottiglia si verificano, esegui un test di carico dell'applicazione fino al verificarsi di un errore. Imposta un numero massimo di istanze, quindi aumenta gradualmente il carico fino a quando l'applicazione non si arresta in modo anomalo.

  • Se il problema di latenza è correlato al deployment di una nuova versione del codice dell'applicazione, esegui il rollback per determinare se è stata la nuova versione a causare l'incidente. Tuttavia, se esegui il deployment continuamente, i deployment frequenti rendono difficile determinare se il deployment ha causato o meno l'incidente in base all'ora di inizio.

  • L'applicazione potrebbe memorizzare le impostazioni di configurazione nel Datastore o altrove. Crea una sequenza temporale delle modifiche alla configurazione per determinare se una di queste corrisponde all'inizio di una latenza elevata.

Modifica del workload

Una modifica del carico di lavoro potrebbe causare una latenza elevata. Alcune metriche di monitoraggio che indicano le variazioni del carico di lavoro includono qps, l'utilizzo delle API e la latenza. Controlla anche se le dimensioni di richiesta e risposta sono cambiate.

Pressione della memoria

Se il monitoraggio mostra un andamento a forma di sega nell'utilizzo della memoria o un calo dell'utilizzo della memoria correlato ai deployment, è possibile che la causa dei problemi di prestazioni sia una perdita di memoria. Una perdita di memoria potrebbe anche causare una garbage collection frequente che porta a una latenza più elevata. Se non riesci a risalire a un problema nel codice, prova a eseguire il provisioning di istanze più grandi con più memoria.

Perdita di risorse

Se un'istanza della tua applicazione mostra una latenza in aumento correlata all'età dell'istanza, è possibile che si verifichi una perdita di risorse che causa problemi di prestazioni. La latenza diminuisce al termine di un deployment. Ad esempio, una struttura di dati che diventa più lenta nel tempo a causa di un utilizzo più elevato della CPU potrebbe causare un rallentamento di qualsiasi carico di lavoro legato alla CPU.

Ottimizzazione del codice

Per ridurre la latenza su App Engine, ottimizza il codice utilizzando i seguenti metodi:

  • Lavoro offline: utilizza Cloud Tasks per impedire alle richieste degli utenti di bloccare l'applicazione in attesa del completamento del lavoro, ad esempio l'invio di email.

  • Chiamate API asincrone: assicurati che il codice non sia bloccato in attesa del completamento di una chiamata API.

  • Chiamate API batch: la versione batch delle chiamate API è in genere più veloce dell'invio di singole chiamate.

  • Denormalizza i modelli di dati: riduci la latenza delle chiamate al livello di persistenza dei dati denormalizzando i modelli di dati.

Dipendenze dell'applicazione

Monitora le dipendenze della tua applicazione per rilevare se gli picchi di latenza sono correlati a un errore di dipendenza.

Una modifica del carico di lavoro e un aumento del traffico potrebbero causare un aumento della latenza di una dipendenza.

Dipendenza non scalabile

Se la dipendenza della tua applicazione non si adatta al numero di istanze App Engine, la dipendenza potrebbe sovraccaricarsi quando il traffico aumenta. Un esempio di dipendenza che potrebbe non essere scalabile è un database SQL. Un numero maggiore di istanze dell'applicazione comporta un numero maggiore di connessioni al database, il che potrebbe causare un errore a cascata impedendo l'avvio del database. Per risolvere il problema:

  1. Esegui il deployment di una nuova versione predefinita che non si connette al database.
  2. Arresta la versione predefinita precedente.
  3. Esegui il deployment di una nuova versione non predefinita che si connette al database.
  4. Esegui la migrazione del traffico alla nuova versione lentamente.

Come misura preventiva, progetta l'applicazione in modo da eliminare le richieste alla dipendenza utilizzando il throttling adattivo.

Errore del livello di memorizzazione nella cache

Per velocizzare le richieste, utilizza più livelli di memorizzazione nella cache, come memorizzazione in una cache perimetrale, Memcache e la memoria all'interno dell'istanza. Un errore in uno di questi livelli di memorizzazione nella cache potrebbe causare un improvviso aumento della latenza. Ad esempio, uno svuotamento della cache Memcache potrebbe causare un aumento delle richieste inviate a un datastore più lento.