Aufwärmanfragen zur Leistungsverbesserung konfigurieren

Sie können mithilfe von Aufwärmanfragen die Anfrage- und Antwortlatenz beim Laden des Codes Ihrer Anwendung in eine neue Instanz verringern.

App Engine muss den Anwendungscode häufig in eine neue Instanz laden. Dazu kann es in folgenden Situationen kommen:

  • Sie stellen eine Version der Anwendung noch einmal bereit.
  • Es werden neue Instanzen erstellt, da die Anfragelast die Kapazität der aktuell ausgeführten Instanzen überschreitet.
  • Die zugrunde liegende Infrastruktur oder Hardware wird gewartet oder repariert.

Wenn Sie den Anwendungscode in eine neue Instanz laden, kann dies zu Ladeanfragen führen. Durch diese Ladeanfragen erhöht sich eventuell die Anfragelatenz für Ihre Nutzer. Mithilfe von Aufwärmanfragen lässt sich dies vermeiden. Aufwärmanfragen laden den Anwendungscode in eine neue Instanz, bevor Live-Anfragen diese Instanz erreichen.

Wenn Aufwärmanfragen für Ihre Anwendung aktiviert sind, ermittelt App Engine, wann Ihre Anwendung eine neue Instanz benötigt, und initiiert dann eine Aufwärmanfrage zur Initialisierung einer neuen Instanz. Diese Ermittlung ist jedoch nicht immer erfolgreich. Daher kann es auch dann zu Ladeanfragen kommen, wenn Aufwärmanfragen in Ihrer Anwendung aktiviert sind. Wenn Ihre Anwendung beispielsweise keinen Traffic bedient, ist die erste Anfrage an die Anwendung immer eine Ladeanfrage, keine Aufwärmanfrage.

Aufwärmanfragen werden wie jede andere Anfrage an Ihre App Engine-Anwendung auf die Instanzstunden angerechnet. In den meisten Fällen werden Sie bei aktivierten Aufwärmanfragen keinen Anstieg der Instanzstunden feststellen, da Ihre Anwendung einfach in einer Aufwärmanfrage statt in einer Ladeanfrage initialisiert wird. Zu einem Anstieg der Instanzstunden kann es kommen, wenn Sie mehr Vorgänge ausführen, z. B. ein Pre-Caching im Rahmen einer Aufwärmanfrage. Wenn Sie für min_idle_instances einen Wert größer als 0 festlegen, treten möglicherweise Aufwärmanfragen auf, wenn diese Instanzen zum ersten Mal gestartet werden. Sie bleiben danach aber verfügbar.

Aufwärmanfragen aktivieren

Aufwärmanfragen werden vom App Engine-Planer genutzt, der die automatische Skalierung der Instanzen anhand der vom Nutzer festgelegten Konfiguration steuert. Sind Aufwärmanfragen aktiviert, stellt App Engine GET-Anfragen an /_ah/warmup. Sie können für diese Anfragen Handler implementieren und so anwendungsspezifische Aufgaben ausführen, z. B. Anwendungsdaten vorab im Cache speichern.

Der Planer startet Instanzen, wenn er feststellt, dass mehr Instanzen benötigt werden. In den Logs können auch dann Aufwärmanfragen enthalten sein, wenn sie deaktiviert sind, da der Planer damit Instanzen startet.

Es werden nicht in jedem Fall Aufwärmanfragen aufgerufen. Unter Umständen werden stattdessen Ladeanfragen gesendet, z. B. dann, wenn es sich um die erste gestartete Instanz handelt oder wenn ein abrupter Anstieg des Traffics zu verzeichnen ist. Bei aktivierten Aufwärmanfragen wird aber nach Möglichkeit versucht, Anfragen an Instanzen zu senden, für die bereits Aufwärmanfragen ausgeführt wurden.

Zur Aktivierung von Aufwärmanfragen fügen Sie das Element warmup unter der Anweisung inbound_services in die Datei app.yaml ein. Beispiel:

inbound_services:
- warmup

Handler erstellen

Sie erstellen einen Handler, der die an /_ah/warmup gesendeten Anfragen verarbeitet. Der Handler sollte jede Aufwärmlogik ausführen, die von Ihrer App benötigt wird.


// 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)
}