Configurazione delle richieste di riscaldamento per migliorare le prestazioni

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

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

  • Quando esegui nuovamente il deployment di una versione dell'app.
  • Quando vengono create nuove istanze a causa del carico delle richieste la capacità del set attuale di istanze in esecuzione.
  • Durante la manutenzione e le riparazioni dell'infrastruttura fisica o dell'infrastruttura sottostante, hardware.

Il caricamento del codice della tua app in una nuova istanza può comportare il caricamento richieste. Il caricamento delle richieste può comportare un aumento della latenza delle richieste per gli utenti, ma è possibile evitare questa latenza utilizzando le richieste di preparazione. Le richieste di riscaldamento caricano del codice dell'app in una nuova istanza prima che le richieste in tempo reale raggiungano l'istanza in questione.

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

Le richieste di preriscaldamento utilizzano le ore di istanza come qualsiasi altra richiesta all'applicazione App Engine. Nella maggior parte dei casi in cui sono abilitate le richieste di riscaldamento, non noterai un aumento delle ore di istanza perché la tua applicazione semplicemente inizializzando una richiesta di warmup invece di una richiesta di caricamento. Il tuo l'utilizzo delle ore di istanza può aumentare se decidi di eseguire altre attività, ad esempio pre-memorizzazione nella cache durante una richiesta di warmup. Se imposti min_idle_instances a un valore superiore a 0, potresti riscontrare richieste di riscaldamento quando queste istanze all'avvio, ma rimarranno disponibili dopo tale data.

Abilitazione delle richieste di riscaldamento in corso...

Le richieste di preriscaldamento vengono utilizzate dal programmatore di App Engine, che controlla la scalabilità automatica delle istanze in base alla configurazione fornita dall'utente. Con le richieste di preriscaldamento attivate, App Engine invia richieste GET a /_ah/warmup. Tu può implementare gestori per questa richiesta per eseguire attività specifiche dell'applicazione, come la pre-memorizzazione nella cache dei dati dell'applicazione.

Il programmatore avvia le istanze quando stabilisce che sono necessarie altre istanze. Le richieste di riscaldamento possono essere visualizzate in log anche se sono disabilitate perché lo scheduler le usa per avviare le istanze.

Tieni presente che non è garantito che le richieste di riscaldamento vengano chiamate. In alcune situazioni vengono inviate richieste di caricamento, ad esempio se l'istanza è la prima l'avvio o la ripida salita nel traffico. Tuttavia, se le richieste di warmup sono abilitate, verrà eseguito un tentativo "best effort" per inviare richieste a istanze già sottoposte a warmup.

Per attivare le richieste di riscaldamento, aggiungi l'elemento warmup sotto la inbound_services nel tuo file app.yaml, ad esempio:

inbound_services:
- warmup

Creazione del gestore

Crea un gestore che elaborerà le richieste inviate a /_ah/warmup. Il gestore deve eseguire qualsiasi logica di riscaldamento necessaria all'app.


// Sample warmup demonstrates usage of the /_ah/warmup handler.
package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"time"

	"cloud.google.com/go/storage"
)

var startupTime time.Time
var client *storage.Client

func main() {
	// Perform required setup steps for the application to function.
	// This assumes any returned error requires a new instance to be created.
	if err := setup(context.Background()); err != nil {
		log.Fatalf("setup: %v", err)
	}

	// Log when an appengine warmup request is used to create the new instance.
	// Warmup steps are taken in setup for consistency with "cold start" instances.
	http.HandleFunc("/_ah/warmup", func(w http.ResponseWriter, r *http.Request) {
		log.Println("warmup done")
	})
	http.HandleFunc("/", indexHandler)

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
		log.Printf("Defaulting to port %s", port)
	}

	log.Printf("Listening on port %s", port)
	if err := http.ListenAndServe(":"+port, nil); err != nil {
		log.Fatal(err)
	}
}

// setup executes per-instance one-time warmup and initialization actions.
func setup(ctx context.Context) error {
	// Store the startup time of the server.
	startupTime = time.Now()

	// Initialize a Google Cloud Storage client.
	var err error
	if client, err = storage.NewClient(ctx); err != nil {
		return err
	}

	return nil
}

// indexHandler responds to requests with our greeting.
func indexHandler(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	uptime := time.Since(startupTime).Seconds()
	fmt.Fprintf(w, "Hello, World! Uptime: %.2fs\n", uptime)
}