Modalità di gestione delle richieste

ID regione

REGION_ID è un codice abbreviato assegnato da Google in base alla regione selezionata al momento della creazione dell'app. Il codice non corrispondono a un paese o a una provincia, anche se potrebbero essere visualizzati alcuni ID regione in modo simile ai codici paese e provincia di uso comune. Per le app create dopo il giorno Febbraio 2020, REGION_ID.r è incluso in URL di App Engine. Per le app esistenti create prima di questa data, l'ID regione è facoltativo nell'URL.

Scopri di più sugli ID regione.

Questo documento descrive il modo in cui l'applicazione App Engine riceve richieste e invia risposte.

Per ulteriori dettagli, consulta l'articolo Riferimento a intestazioni e risposte delle richieste.

Se la tua applicazione utilizza i servizi, puoi indirizzare le richieste a un servizio specifico o a una versione specifica di quel servizio. Per ulteriori informazioni sull'addressability dei servizi, consulta In che modo vengono instradate le richieste.

Gestione delle richieste

L'applicazione è responsabile dell'avvio di un server web e della gestione delle richieste. Puoi utilizzare qualsiasi framework web disponibile per il tuo linguaggio di sviluppo.

Quando App Engine riceve una richiesta web per la tua applicazione, richiama il servlet che corrisponde all'URL, come descritto nel File web.xml nella directory WEB-INF/. Supporta Java Servlet specifiche dell'API 2.5 o 3.1; per fornire i dati della richiesta al servlet e accettare i dati di risposta.

App Engine esegue più istanze dell'applicazione, ogni istanza dispone di un proprio server web per la gestione delle richieste. Ogni richiesta può essere indirizzata a qualsiasi istanza, quindi non vengono inviate necessariamente richieste consecutive dello stesso utente. alla stessa istanza. Il numero di istanze può essere modificato automaticamente in base alle variazioni del traffico.

Per impostazione predefinita, ciascun server web elabora una sola richiesta alla volta. Per inviare più richieste a ciascun server web in parallelo, contrassegna la tua applicazione come sicura per i thread aggiungendo un elemento <threadsafe>true</threadsafe> al file appengine-web.xml.

Il seguente esempio di classe servlet mostra un semplice messaggio nel browser dell'utente.

// With @WebServlet annotation the webapp/WEB-INF/web.xml is no longer required.
@WebServlet(name = "requests", description = "Requests: Trivial request", urlPatterns = "/requests")
public class RequestsServlet extends HttpServlet {

  @Override
  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    resp.setContentType("text/plain");
    resp.getWriter().println("Hello, world");
  }
}

Quote e limiti

App Engine alloca automaticamente le risorse all'applicazione aumenta il traffico. Tuttavia, ciò è vincolato dalle seguenti restrizioni:

  • App Engine riserva la capacità di scalabilità automatica per le applicazioni bassa latenza, dove l'applicazione risponde alle richieste in meno di un secondo.

  • Le applicazioni che sono fortemente legate alla CPU possono inoltre subire una latenza aggiuntiva al fine di condividere in modo efficiente le risorse con altre applicazioni sulla stessa server web. Le richieste di file statici sono esenti da questi limiti di latenza.

Ogni richiesta in arrivo all'applicazione viene conteggiata ai fini del limite di Richieste. I dati inviati in risposta a una richiesta vengono conteggiati ai fini del Limite Larghezza di banda in uscita (fatturabile).

Sia le richieste HTTP che quelle HTTPS (sicure) vengono conteggiate ai fini dei limiti di Richieste, Larghezza di banda in entrata (fatturabile) e Larghezza di banda in uscita (fatturabile). La pagina dei dettagli delle quote della console Google Cloud riporta anche Richieste sicure, Larghezza di banda in entrata sicura e Larghezza di banda in uscita sicura come valori separati a scopo informativo. Solo le richieste HTTPS vengono conteggiate per questi valori. Per ulteriori informazioni, consulta la pagina Quote.

I seguenti limiti si applicano nello specifico all'uso dei gestori delle richieste:

Limite Quantità
Dimensioni richiesta 32 megabyte
Dimensione della risposta 32 megabyte
Timeout richiesta Dipende dal tipo di scalabilità utilizzato dalla tua app
Numero totale massimo di file (file di app e file statici) 10.000 in totale
1000 per directory
Dimensione massima del file di un'applicazione 32 megabyte
Dimensione massima di un file statico 32 megabyte
Dimensione totale massima di tutti i file statici e dell'applicazione Il primo gigabyte è gratuito
$ 0,026 per gigabyte al mese dopo il primo gigabyte
Timeout richiesta in attesa 10 secondi
Dimensione massima di un singolo campo dell'intestazione della richiesta 8 kilobyte per i runtime di seconda generazione nell'ambiente standard. Le richieste a questi runtime con campi di intestazione superiori a 8 kilobyte restituiranno errori HTTP 400.

Limiti per le richieste

Tutte le richieste HTTP/2 verranno tradotte in richieste HTTP/1.1 quando vengono inoltrate al server dell'applicazione.

Limiti di risposta

  • Le risposte dinamiche sono limitate a 32 MB. Se un gestore di script genera una risposta superiore a questo limite, il server restituisce una risposta vuota con un codice di stato 500 (Errore interno del server). Questo limite non si applica alle risposte che forniscono dati nell'archivio BLOB legacy Cloud Storage.

  • Il limite di intestazione di risposta è 8 KB per i runtime di seconda generazione. Le intestazioni di risposta che superano questo limite restituiranno errori HTTP 502, con log che mostrano upstream sent too big header while reading response header from upstream.

Intestazioni delle richieste

Una richiesta HTTP in arrivo include le intestazioni HTTP inviate dal client. Per motivi di sicurezza, alcune intestazioni vengono sottoposte a sanificazione o modificate da proxy intermedi prima di raggiungere l'applicazione.

Per ulteriori informazioni, consulta Riferimento alle intestazioni delle richieste.

Gestione dei timeout delle richieste

App Engine è ottimizzato per applicazioni con richieste di breve durata, di solito quelle che impiegano qualche centinaio di millisecondi. Un'app efficiente risponde rapidamente alla maggior parte delle richieste. Un'app che non si adatta bene alla scalabilità con l'infrastruttura di App Engine. Per garantire questo livello di prestazioni, esiste un timeout della richiesta massimo imposto dal sistema entro il quale ogni app deve rispondere.

Se la tua app supera questa scadenza, App Engine interrompe il gestore delle richieste. L'ambiente di runtime Java interrompe il servlet generando un com.google.apphosting.api.DeadlineExceededException. Se non esiste un gestore di richieste che rilevi questa eccezione, l'ambiente di runtime restituirà un errore HTTP 500 del server al client.

Se è presente un gestore delle richieste e viene rilevato DeadlineExceededException, l'ambiente di runtime concede al gestore delle richieste il tempo (meno di un secondo) per preparare una risposta personalizzata. Se il gestore delle richieste impiega più di un secondo dopo aver sollevato l'eccezione per preparare una risposta personalizzata, verrà sollevato un HardDeadlineExceededError.

DeadlineExceededExceptions e HardDeadlineExceededErrors forzano l'applicazione l'arresto della richiesta e arrestare l'istanza.

Per sapere quanto tempo rimane prima della scadenza, la domanda può import com.google.apphosting.api.ApiProxy e chiama ApiProxy.getCurrentEnvironment().getRemainingMillis(). Ciò è utile se l'applicazione prevede di iniziare per alcuni lavori che potrebbero richiedere troppo tempo; se sai che ci vogliono cinque secondi per elaborare un'unità di lavoro, ma getRemainingMillis() restituisce meno tempo, non ha senso iniziare quell'unità di al lavoro.

Risposte

App Engine chiama il servlet con un oggetto di richiesta e una risposta , quindi attende che il servlet completi l'oggetto risposta e lo ritorni. Quando il servlet ritorna, i dati dell'oggetto risposta vengono inviati all'utente.

Esistono limiti di dimensioni che si applicano alle risposte genera e la risposta può essere modificata prima di essere restituita al client.

Per ulteriori informazioni, consulta l'articolo Riferimento alle richieste di risposte.

Risposte dinamiche

App Engine non supporta le risposte in streaming in cui i dati vengono inviati al client in blocchi incrementali durante l'elaborazione di una richiesta. Tutti i dati del codice vengono raccolti come descritto sopra e inviati come singola risposta HTTP.

Compressione delle risposte

App Engine fa del suo meglio per pubblicare contenuti compressi (con gzip) per i client che li supportano. Per determinare se i contenuti devono essere compressi, App Engine esegue le seguenti operazioni quando riceve una richiesta:

  1. Verifica se il client può ricevere in modo affidabile le risposte compresse visualizzando entrambe le intestazioni Accept-Encoding e User-Agent nella richiesta. Questo approccio evita alcuni bug noti relativi ai contenuti compressi con gzip nei browser più diffusi.

  2. Per confermare che la compressione dei contenuti è appropriata, visualizza il Intestazione Content-Type che hai configurato per il di gestione delle risposte. In generale, la compressione è appropriata per i tipi di contenuti basati su testo e non per i tipi di contenuti binari.

Tieni presente quanto segue:

  • Un client può forzare la compressione dei tipi di contenuti basati su testo impostando sia delle intestazioni della richiesta Accept-Encoding e User-Agent a gzip.

  • Se per una richiesta non è specificato gzip nell'intestazione Accept-Encoding, App Engine non comprime i dati di risposta.

  • Il Frontend di Google memorizza nella cache le risposte dei gestori di directory e file statici di App Engine. A seconda di una serie di fattori, ad esempio il tipo di dati della risposta memorizzati nella cache per primo, le intestazioni Vary che hai specificato nella risposta e le intestazioni incluse nella richiesta, un client potrebbe richiedere dati compressi, ma ricevere dati non compressi e viceversa. Per maggiori informazioni, consulta Memorizzazione nella cache delle risposte.

Memorizzazione nella cache delle risposte

Il frontend di Google e potenzialmente il browser dell'utente e altri server proxy intermediari per la memorizzazione nella cache memorizzeranno nella cache le risposte della tua app come indicato dalle intestazioni di memorizzazione nella cache standard specificate nella risposta. Puoi specificare queste intestazioni di risposta attraverso il tuo framework, direttamente o mediante il file statico e la directory di App Engine e i gestori di rete.

In Google Frontend, la chiave della cache è l'URL completo della richiesta.

Memorizzazione nella cache dei contenuti statici

Per garantire che i clienti ricevano sempre i contenuti statici aggiornati non appena possibile. pubblicata, ti consigliamo di pubblicare contenuti statici come css/v1/styles.css. Il Frontend di Google non convalida la cache (controlla la presenza di contenuti aggiornati) fino alla scadenza della cache. Anche dopo scadono, la cache non viene aggiornata finché i contenuti non vengono Modifiche agli URL.

Le seguenti intestazioni di risposta che puoi impostato in appengine-web.xml influenzano come e quando Google Frontend memorizza i contenuti nella cache:

  • Cache-Control deve essere impostato su public affinché Google Frontend possa memorizzare nella cache contenuti; potrebbe anche essere memorizzata nella cache da Google Frontend a meno che non specifichi Istruzione Cache-Control private o no-store. Se non imposti questo header in appengine-web.xml , App Engine lo aggiunge automaticamente per tutte le risposte gestite da un gestore di directory o file statico. Per maggiori informazioni informazioni, consulta la sezione Intestazioni aggiunte o sostituite.

  • Vary: per consentire alla cache di restituire risposte diverse per un URL in base a inviate nella richiesta, impostare uno o più dei seguenti valori nell'intestazione della risposta Vary: Accept, Accept-Encoding, Origin o X-Origin

    Data la potenziale cardinalità elevata, i dati non verranno memorizzati nella cache Vary valori.

    Ad esempio:

    1. Specifica la seguente intestazione della risposta:

      Vary: Accept-Encoding

    2. La tua app riceve una richiesta che contiene l'intestazione Accept-Encoding: gzip. App Engine restituisce una risposta compressa e Google Frontend memorizza nella cache la versione compressa con gzip dei dati di risposta. Tutte le richieste successive per questo URL che contiene l'intestazione Accept-Encoding: gzip riceverà i dati compressi con gzip dalla cache fino all'invalidazione della cache (a causa i contenuti che cambiano dopo la scadenza della cache).

    3. La tua app riceve una richiesta che non contiene l'intestazione Accept-Encoding. App Engine restituisce una risposta non compressa e Google Frontend memorizza nella cache la versione non compressa dei dati della risposta. Tutti i successivi richieste per questo URL che non contengono l'intestazione Accept-Encoding riceverà i dati compressi dalla cache fino a quando invalidato.

    Se non specifichi un'intestazione di risposta Vary, il frontend di Google crea una singola voce della cache per l'URL e la utilizza per tutte le richieste, indipendentemente dalle intestazioni nella richiesta. Ad esempio:

    1. Non specifichi l'intestazione della risposta Vary: Accept-Encoding.
    2. Una richiesta contiene l'intestazione Accept-Encoding: gzip e la versione compressa con gzip dei dati della risposta verrà memorizzata nella cache.
    3. Una seconda richiesta non contiene l'intestazione Accept-Encoding: gzip. Tuttavia, poiché la cache contiene una versione compressa con gzip dei dati della risposta, la risposta verrà compressa in formato gzip anche se il client ha richiesto e i dati di Google Cloud.

Anche le intestazioni nella richiesta influiscono sulla memorizzazione nella cache:

  • Se la richiesta contiene un'intestazione Authorization, i contenuti non saranno memorizzati nella cache da Google Frontend.

Scadenza della cache

Per impostazione predefinita, le intestazioni di memorizzazione nella cache aggiunte ai gestori di directory e file statici di App Engine alle risposte ordinano ai client e ai proxy web, come il frontend di Google, di far scadere la cache dopo 10 minuti.

Dopo che un file è stato trasmesso con una determinata data e ora di scadenza, in genere non è possibile rimuoverlo dalle cache del proxy web, anche se l'utente svuota la cache del proprio browser. Il nuovo deployment di una nuova versione dell'app non reimposta le cache. Pertanto, se prevedi di modificare un file statico, questo dovrebbe avere un scadenza breve (meno di un'ora). Nella maggior parte dei casi, il valore predefinito di 10 minuti per la data e l'ora di scadenza è appropriato.

Puoi modificare la scadenza predefinita per tutti i gestori di file e directory statici specificando static-files in appengine-web.xml .

Logging

L'applicazione può scrivere informazioni nei log dell'applicazione utilizzando java.util.logging.Logger. I dati di log relativi alla tua applicazione possono essere visualizzati nella console Google Cloud utilizzando Cloud Logging. A ogni richiesta registrata viene assegnato un ID richiesta, un identificatore univoco globale basato sull'ora di inizio della richiesta. La console Google Cloud è in grado di riconoscere i livelli di log della classe Logger e di visualizzare in modo interattivo i messaggi a diversi livelli.

Tutto ciò che il servlet scrive nello stream di output standard (System.out) e nello stream di errori standard (System.err) viene acquisito da App Engine e registrato nei log dell'applicazione. Righe scritte nel flusso di output standard vengono registrati nel campo "INFO" e le righe scritte nel flusso di errori standard vengono registrati all'account "WARNING" livello. Qualsiasi framework di logging (come log4j) che i log nei flussi di output o di errore. Tuttavia, per un controllo più granulare della visualizzazione del livello di log nella console Google Cloud, il framework di logging deve utilizzare un adattatore java.util.logging.

// With @WebServlet annotation the webapp/WEB-INF/web.xml is no longer required.
@WebServlet(
    name = "RequestLogging",
    description = "Requests: Logging example",
    urlPatterns = "/requests/log"
)
public class LoggingServlet extends HttpServlet {

  private static final Logger log = Logger.getLogger(LoggingServlet.class.getName());

  @Override
  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    log.info("An informational message.");
    log.warning("A warning message.");
    log.severe("An error message.");
    // ...
  }
}

L'SDK Java di App Engine include un file modello logging.properties nella directory appengine-java-sdk/config/user/. Per utilizzarlo, copia il file in la directory WEB-INF/classes (o in un'altra posizione in WAR), il sistema da java.util.logging.config.file a "WEB-INF/logging.properties" (o a seconda del percorso che scegli rispetto alla radice dell'applicazione). Puoi impostare le opzioni proprietà nel File appengine-web.xml come che segue:

<appengine-web-app CPCO="http://appengine.google.com/ns/1.0"> ... &lt;system-properties&gt; &lt;property name=&quot;java.util.logging.config.file&quot; value=&quot;WEB-INF/logging.properties&quot; /&gt; &lt;/system-properties&gt; &lt;/appengine-web-app&gt;

Il servlet registra i messaggi utilizzando il livello di log INFO (utilizzando log.info()). Il livello di log predefinito è WARNING, che elimina i messaggi INFO dall'output. Per cambiare il livello di log, modifica il file logging.properties.

L'ambiente

Tutte le proprietà di sistema e le variabili di ambiente sono private per la tua applicazione. L'impostazione di una proprietà di sistema influisce solo sulla vista dell'applicazione di tale proprietà, e non quella della JVM.

Puoi impostare le proprietà di sistema e le variabili di ambiente per la tua app in: descrittore del deployment.

App Engine imposta diverse proprietà di sistema che identificano il runtime questo ambiente:

  • com.google.appengine.runtime.environment è "Production" quando viene eseguito su App Engine e "Development" quando viene eseguito nel server di sviluppo.

    Oltre a usare System.getProperty(), puoi accedere al sistema con le nostre proprietà anti-tipo API. Ad esempio:

    if (SystemProperty.environment.value() ==
        SystemProperty.Environment.Value.Production) {
        // The app is running on App Engine...
    }
    
  • com.google.appengine.runtime.version è l'ID versione dell'ambiente di runtime, ad esempio "1.3.0". Puoi ottenere la versione richiamando seguire: String version = SystemProperty.version.get();

  • com.google.appengine.application.id è l'ID dell'applicazione. Puoi ottenere ID richiamando quanto segue: String ID = SystemProperty.applicationId.get();

  • com.google.appengine.application.version è la versione principale e secondaria del servizio dell'applicazione attualmente in esecuzione, ad esempio "X.Y". Il numero della versione principale ("X") è specificata nel file appengine-web.xml del servizio. Il minorenne numero di versione ("Y") viene impostato automaticamente quando ogni versione dell'app viene sono state caricate in App Engine. Puoi ottenere l'ID richiamando quanto segue: String ID = SystemProperty.applicationVersion.get();

    Sul server web di sviluppo, la versione principale restituita è sempre la versione del servizio predefinito e la versione secondaria è sempre "1".

App Engine imposta inoltre le seguenti proprietà di sistema quando inizializza la JVM su un server app:

  • file.separator
  • path.separator
  • line.separator
  • java.version
  • java.vendor
  • java.vendor.url
  • java.class.version
  • java.specification.version
  • java.specification.vendor
  • java.specification.name
  • java.vm.vendor
  • java.vm.name
  • java.vm.specification.version
  • java.vm.specification.vendor
  • java.vm.specification.name
  • user.dir

ID istanze

Puoi recuperare l'ID l'istanza che gestisce una richiesta utilizzando questo codice:

com.google.apphosting.api.ApiProxy.getCurrentEnvironment().getAttributes().get("com.google.appengine.instance.id")

Nell'ambiente di produzione, un amministratore che ha eseguito l'accesso può utilizzare l'ID in un URL: https://INSTANCE_ID-dot-VERSION_ID-dot-SERVICE_ID-dot-PROJECT_ID.REGION_ID.r.appspot.com. La richiesta verrà indirizzata a per quell'istanza specifica. Se l'istanza non può gestire la richiesta, restituisce immediatamente un codice 503.

ID richieste

Al momento della richiesta, puoi salvare l'ID richiesta, che è univoco per la richiesta. L'ID richiesta può essere utilizzato in un secondo momento per correlare una richiesta ai relativi log.

Il seguente codice mostra come ottenere l'ID richiesta nel contesto di una richiesta:

com.google.apphosting.api.ApiProxy.getCurrentEnvironment().getAttributes().get("com.google.appengine.runtime.request_log_id")

Forzare le connessioni HTTPS

Per motivi di sicurezza, tutte le applicazioni devono incoraggiare i client a connettersi https. Per indicare al browser di preferire https a http per una determinata pagina o per l'intero dominio, imposta l'intestazione Strict-Transport-Security nelle risposte. Ad esempio:

Strict-Transport-Security: max-age=31536000; includeSubDomains
Per impostare questo intestazione per tutti i contenuti statici pubblicati dalla tua app, aggiungila agli handler di file e directory statici della tua app.

L'impostazione di questa intestazione è supportata dalla maggior parte dei framework delle app e dei server web per le risposte generate dal codice. Per informazioni sull'intestazione Strict-Transport-Security in Spring Boot, consulta HTTP Strict Transport Security (HSTS).

Gestione del lavoro in background asincrono

Il lavoro in background è qualsiasi lavoro eseguito dalla tua app per una richiesta dopo che hai fornito la risposta HTTP. Evita di eseguire operazioni in background nella tua app e controlla il codice per assicurarti che tutte le operazioni asincrone vengano completate prima di inviare la risposta.

Per i job a lunga esecuzione, consigliamo di utilizzare Cloud Tasks. Con Cloud Tasks, le richieste HTTP hanno una lunga durata e restituiscono solo una risposta al termine del lavoro asincrono.