Risolvere i problemi di latenza elevata nelle app App Engine

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

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

Definisci l'ambito del problema di latenza

Definisci l'ambito del problema ponendo le seguenti domande:

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

Un servizio potrebbe avere un monitoraggio e una registrazione personalizzati che puoi utilizzare per restringere ulteriormente l'ambito del problema. Definire l'ambito del problema ti guiderà verso la probabile causa principale e determinerà i passaggi successivi per la risoluzione dei problemi.

Identificare la causa

Determina quale componente nel percorso della richiesta ha maggiori probabilità di causare latenza o errori. I componenti principali nel percorso della richiesta sono i seguenti:

Client --> Internet --> Google Front End (GFE) --> Infrastruttura di pubblicazione di App Engine --> Istanza del servizio

Se le informazioni precedenti non ti indirizzano all'origine dell'errore, applica le seguenti strategie durante la revisione dell'integrità e del rendimento dell'istanza del servizio:

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

  2. Se il numero di istanze di servizio non è stato scalato in modo da corrispondere ai livelli di traffico, le istanze potrebbero essere sovraccariche, con conseguente aumento di errori e latenza.

  3. Se in Cloud Monitoring noti un aumento degli errori o della latenza, il problema potrebbe essere a monte del bilanciamento del carico, che registra le metriche di App Engine. Nella maggior parte dei casi, questo indica un problema nelle istanze del 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 stavano iniziando a non funzionare prima che il bilanciatore del carico smettesse di instradare le richieste.

Risoluzione dei problemi

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

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

Internet

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

Connettività a internet scadente

Per determinare se il problema è una 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 Google Front End più vicino. Per le connessioni lente, esegui ulteriori operazioni di risoluzione dei problemi utilizzando traceroute per determinare quale hop della rete causa il ritardo.

Esegui test da client in diverse posizioni geografiche. App Engine instrada automaticamente le richieste al data center Google più vicino, che varia in base alla posizione del client.

Larghezza di banda insufficiente

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

Google Front End (GFE)

La tua applicazione potrebbe riscontrare problemi di latenza a causa di un routing errato, di richieste parallele inviate dai client HTTP/2 o della terminazione delle connessioni SSL.

Mappare un IP 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 client utilizzato nella ricerca DNS. Se il resolver DNS del client non utilizza il protocollo EDNS0, Google potrebbe non instradare 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 head-of-line nel GFE. Per risolvere il problema, i client devono utilizzare il protocollo QUIC.

Terminazione SSL per domini personalizzati

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 aggiungere 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 scalabilità automatica.

Incidenti a livello di servizio

Google pubblica i dettagli di un problema grave a livello di servizio nella dashboard Service Health. Tuttavia, Google esegue implementazioni graduali, quindi è improbabile che un incidente a livello di servizio influisca su tutte le tue istanze contemporaneamente.

Scalabilità automatica

Latenza elevata o errori possono verificarsi a causa dei seguenti scenari di scalabilità automatica:

  • Aumentare il traffico troppo rapidamente: la scalabilità automatica di App Engine potrebbe non scalare le istanze alla stessa velocità dell'aumento del traffico, causando un sovraccarico temporaneo. In genere, il sovraccarico si verifica quando il traffico viene generato da un programma per computer anziché dagli utenti finali. Per risolvere il problema, limita il 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 deve scalare più rapidamente del possibile, senza influire sulla latenza. Il traffico degli utenti finali di solito 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 tuo 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 risposte del server con il codice di stato 500 e il messaggio "Request was aborted after waiting too long to attempt to service your request" (Richiesta interrotta dopo un'attesa troppo lunga per tentare di elaborarla), significa che la richiesta è scaduta nella coda in attesa mentre attendeva un'istanza inattiva.

    • Potresti notare un aumento del tempo di attesa con lo scaling manuale anche se hai eseguito il provisioning di un numero sufficiente di istanze. Ti consigliamo di non utilizzare lo scaling manuale se la tua applicazione gestisce il traffico degli utenti finali. La scalabilità manuale è più adatta a workload come le code di attività.

    • Lo scaling di base riduce al minimo i costi a scapito della latenza. Ti consigliamo di non utilizzare lo scaling 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 regoli le impostazioni di scalabilità per ridurre i costi riducendo al minimo le istanze inattive, corri il rischio di picchi di latenza se il carico aumenta improvvisamente.

Ti consigliamo di confrontare il rendimento con le impostazioni di scalabilità predefinite e poi di eseguire un nuovo benchmark dopo ogni modifica di queste impostazioni.

Deployment

Una latenza elevata poco dopo un deployment indica che non hai eseguito lo scale up in modo sufficiente prima di eseguire la migrazione del traffico. Le istanze più recenti potrebbero non aver riscaldato 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 di versione di una versione esistente del servizio. Se riutilizzi un nome di 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 delle applicazioni e al codice sorgente 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 instrumentare l'applicazione utilizzando logging, monitoraggio e 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 la lingua che potrebbero non essere possibile eseguire in App Engine.

  • Per comprendere meglio in che modo l'applicazione non funziona e quali colli di bottiglia si verificano, esegui il test di carico dell'applicazione fino all'errore. Imposta un numero massimo di istanze, quindi aumenta gradualmente il carico finché l'applicazione non ha esito negativo.

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

  • La tua applicazione potrebbe archiviare le impostazioni di configurazione in Datastore o altrove. Crea una cronologia delle modifiche alla configurazione per determinare se qualcuna di queste corrisponde all'inizio della latenza elevata.

Modifica del workload

Una modifica del workload potrebbe causare un aumento della latenza. Alcune metriche di monitoraggio che indicano modifiche del workload includono qps, utilizzo delle API e latenza. Controlla anche le modifiche alle dimensioni delle richieste e delle risposte.

Pressione della memoria

Se il monitoraggio mostra un andamento a dente di sega nell'utilizzo della memoria o un calo dell'utilizzo della memoria correlato alle implementazioni, una perdita di memoria potrebbe essere la causa dei problemi di prestazioni. Una perdita di memoria potrebbe anche causare una frequente garbage collection che porta a una latenza maggiore. Se non riesci a ricondurre questo problema 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 crescente correlata all'età dell'istanza, potresti avere una perdita di risorse che causa problemi di prestazioni. La latenza diminuisce al termine di un deployment. Ad esempio, una struttura di dati che rallenta nel tempo a causa di un maggiore utilizzo della CPU potrebbe causare il 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 che le richieste degli utenti blocchino 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 chiamate individuali.

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

Dipendenze dell'applicazione

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

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

Dipendenza non scalabile

Se la dipendenza della tua applicazione non viene scalata man mano che aumenta il 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, segui questi passaggi:

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

Come misura preventiva, progetta la tua applicazione in modo da eliminare le richieste alla dipendenza utilizzando la limitazione adattiva.

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 in-instance. Un errore in uno di questi livelli di memorizzazione nella cache potrebbe causare un improvviso aumento della latenza. Ad esempio, uno svuotamento di Memcache potrebbe causare l'invio di più richieste a un datastore più lento.