Configurare le richieste di warmup per migliorare le prestazioni

Puoi utilizzare le richieste di warmup per ridurre la latenza di richieste e risposte durante il caricamento del codice dell'app in un'istanza appena creata.

App Engine deve spesso caricare il codice dell'app in una nuova istanza. Il caricamento di un'istanza può verificarsi nelle seguenti situazioni:

  • Quando riesegui il deployment di una versione della tua app.
  • Quando vengono create nuove istanze a causa del carico delle richieste che supera la capacità del set attuale di istanze in esecuzione.
  • Quando si verificano interventi di manutenzione e riparazione dell'infrastruttura sottostante o dell'hardware fisico.

Il caricamento del codice della tua app in una nuova istanza può comportare il caricamento delle richieste. Le richieste di caricamento possono comportare una maggiore latenza delle richieste per i tuoi utenti, ma puoi evitare questa latenza utilizzando le richieste di preparazione. Le richieste di warmup caricano il codice della tua app in una nuova istanza prima che eventuali richieste in tempo reale raggiungano l'istanza.

Se le richieste di warmup sono abilitate per la tua applicazione, App Engine tenta di rilevare quando l'applicazione ha bisogno di una nuova istanza e avvia una richiesta di warmup per inizializzare una nuova istanza. Tuttavia, questi tentativi di rilevamento non funzionano sempre. Di conseguenza, potresti riscontrare richieste di caricamento, anche se nella tua app sono abilitate richieste di preparazione. Ad esempio, se la tua app non genera traffico, la prima richiesta all'app sarà sempre una richiesta di caricamento, non una richiesta di warmup.

Le richieste di warmup utilizzano le ore di istanza come qualsiasi altra richiesta all'applicazione App Engine. Nella maggior parte dei casi in cui le richieste di warmup sono abilitate, non noterai un aumento delle ore di istanza perché l'applicazione viene semplicemente inizializzata in una richiesta di warmup anziché in una richiesta di caricamento. L'utilizzo dell'ora di istanza può aumentare se decidi di svolgere più attività, ad esempio la pre-memorizzazione nella cache durante una richiesta di warmup. Se imposti min_idle_instances su un valore superiore a 0, potresti riscontrare richieste di warmup al primo avvio di queste istanze, ma rimarranno disponibili dopo questo periodo.

La richiesta di warmup predefinita fa sì che tutti i file JAR vengano indicizzati in memoria e inizializza l'applicazione e i filtri.

Abilitazione delle richieste di warmup

Le richieste di warmup vengono utilizzate dallo scheduler di App Engine, che controlla la scalabilità automatica delle istanze in base alla configurazione fornita dall'utente. Nel runtime Java di App Engine, le richieste di warmup sono abilitate per impostazione predefinita, pertanto App Engine invia richieste GET a /_ah/warmup, che ti consente di rispondere e inizializzare il codice della tua applicazione in base alle esigenze. Puoi rispondere alle richieste di warmup utilizzando uno dei seguenti metodi:

Utilizzo di un servlet <load-on-startup>
Il modo più semplice per fornire la logica di warmup è contrassegnare i servlet come <load-on-startup> nel file di configurazione web.xml.
Utilizzo di un ServletContextListener
Ti consente di eseguire logica personalizzata prima che una qualsiasi servlet venga richiamata per la prima volta tramite una richiesta di warmup o di caricamento.
Utilizzo di un servlet di warmup personalizzato
L'utilizzo di un servlet di warmup personalizzato richiama il metodo service del servlet solo durante una richiesta di warmup anziché durante le richieste di caricamento.

A seconda di quale dei seguenti metodi scegli, potresti dover implementare un tuo gestore per /_ah/warmup.

Prima di iniziare

Quando le richieste di warmup sono abilitate, lo scheduler avvia le istanze quando determina che sono necessarie più istanze. Lo scheduler utilizza le richieste di warmup per avviare l'app, pertanto vedrai i log anche se l'app non elabora queste richieste di warmup.

Il seguente messaggio indica le richieste di warmup nei log /_ah/warmup:

This request caused a new process to be started for your application, and thus caused your application code to be loaded for the first time. This request may thus take longer and use more CPU than a typical request for your application.

Tieni presente che non è garantito che le richieste di warmup vengano chiamate. In alcune situazioni vengono invece inviate le richieste di caricamento, ad esempio se l'istanza è la prima avviata o se il traffico è in forte aumento. Tuttavia, ci sarà un tentativo "best effort" di inviare richieste a istanze già sottoposte a warmup se le richieste di warmup sono abilitate.

In Java 8, le richieste di warmup sono abilitate per impostazione predefinita. Per abilitarle, aggiungi - warmup all'istruzione inbound_services in appengine-web.xml. Poiché per impostazione predefinita i preparativi sono abilitati, devi abilitarli esplicitamente solo se in precedenza hai eseguito il deployment di un'applicazione con richieste di warmup disabilitate in appengine-web.xml. In questo caso, devi impostare il valore <warmup-requests-enabled> su true ed eseguire nuovamente il deployment.

Utilizzo di un servlet <load-on-startup>

Il modo più semplice per fornire la logica di warmup è contrassegnare le tue servlet come <load-on-startup> in web.xml. Questo metodo non richiede modifiche al codice dell'applicazione e inizializza tutti i servlet specificati quando viene inizializzata l'applicazione.

Nel file web.xml, aggiungi l'elemento <load-on-startup>1</load-on-startup> all'elemento <servlet> per i servlet che vuoi caricare all'avvio. Ad esempio:

<servlet>
  <servlet-name>my-servlet</servlet-name>
  <servlet-class>com.company.MyServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>

Queste righe caricano la classe servlet specificata e richiamano il metodo init() del servlet. La richiesta di warmup inizializza i servlet specificati prima di gestire qualsiasi richiesta in tempo reale. Tuttavia, in assenza di richiesta di warmup, i servlet specificati in <load-on-startup> vengono registrati al momento della prima richiesta a una nuova istanza, il che genera una richiesta di caricamento. Come indicato in precedenza, App Engine potrebbe non inviare una richiesta di warmup ogni volta che l'applicazione ha bisogno di una nuova istanza.

Uso di un ServletContextListener

Se vuoi eseguire una logica personalizzata prima che i servlet vengano richiamati:

  1. Registra un ServletContextListener nel tuo file web.xml.

    <listener>
      <listener-class>com.company.MyListener</listener-class>
    </listener>
    
  2. Specifica una classe insieme al codice del servlet e del filtro:

    public class MyListener implements ServletContextListener {
      public void contextInitialized(ServletContextEvent event) {
        // This will be invoked as part of a warmup request, or
        // the first user request if no warmup request was invoked.
      }
      public void contextDestroyed(ServletContextEvent event) {
        // App Engine does not currently invoke this method.
      }
    }
    

ServletContextListener viene eseguito durante una richiesta di warmup. Se non esiste una richiesta di warmup, viene eseguita alla prima richiesta a una nuova istanza. Ciò potrebbe comportare il caricamento delle richieste.

Utilizzo di un servlet di warmup personalizzato

Il servlet di warmup personalizzato richiama il metodo service del servlet solo durante una richiesta di warmup. Inserendo una logica costosa in un servlet di warmup personalizzato, puoi evitare un aumento dei tempi di caricamento delle richieste.

Per creare un servlet di warmup personalizzato, esegui semplicemente l'override della definizione del servlet integrato per _ah_warmup in web.xml:

<servlet>
  <servlet-name>_ah_warmup</servlet-name>
  <servlet-class>com.company.MyWarmupServlet</servlet-class>
</servlet>