Configurer des requêtes de préchauffage pour améliorer les performances

Vous pouvez utiliser des requêtes de préchauffage afin d'éviter la latence des requêtes et des réponses lorsque le code de votre application est chargé dans une instance nouvellement créée.

App Engine doit fréquemment charger le code de l'application dans une nouvelle instance. Le chargement d'une instance peut se produire dans les situations suivantes :

  • Lorsque vous redéployez une version de votre application
  • Lorsque des instances sont créées parce que la charge générée par les requêtes dépasse la capacité de l'ensemble actuel des instances en cours d'exécution
  • En cas d'opérations de maintenance et de réparation de l'infrastructure sous-jacente ou du matériel physique

Le chargement du code de l'application dans une nouvelle instance peut déclencher des requêtes de chargement. Ces requêtes peuvent entraîner une augmentation de la latence de requête pour vos utilisateurs, mais vous pouvez éviter ce temps de latence grâce à des requêtes de préchauffage. Les requêtes de préchauffage chargent le code de votre application dans une nouvelle instance avant que des requêtes en temps réel n'atteignent cette instance.

Si les requêtes de préchauffage sont activées pour votre application, App Engine tente de détecter à quel moment cette dernière a besoin d'une nouvelle instance, et lance une requête de préchauffage pour initialiser une nouvelle instance. Cependant, ces tentatives de détection ne fonctionnent pas à chaque fois. Par conséquent, vous pouvez subir des requêtes de chargement, même si les requêtes de préchauffage sont activées dans votre application. Par exemple, si votre application ne diffuse aucun trafic, la première requête envoyée à l'application sera toujours une requête de chargement, et non une requête de préchauffage.

Les requêtes de préchauffage utilisent des instances-heures comme toute autre requête adressée à votre application App Engine. Dans la plupart des cas où les requêtes de préchauffage sont activées, vous ne remarquerez pas d'augmentation du nombre d'instances-heures, car votre application est simplement initialisée dans une requête de préchauffage. Vos instances-heures peuvent augmenter si vous décidez d'effectuer plus de travail, comme la mise en cache préalable lors d'une requête de préchauffage. Si vous définissez min_idle_instances sur une valeur supérieure à 0, vous risquez de recevoir des requêtes de préchauffage lorsque ces instances démarrent pour la première fois, mais elles resteront disponibles par la suite.

Activer des requêtes de préchauffage

Les requêtes de préchauffage sont employées par le programmeur App Engine, qui contrôle l'autoscaling des instances en fonction de la configuration fournie par l'utilisateur. Lorsque les requêtes de préchauffage sont activées, App Engine émet des requêtes GET auprès de /_ah/warmup. Vous pouvez mettre en œuvre des gestionnaires pour cette requête afin d'effectuer des tâches propres à l'application, telles que la mise en cache préalable des données d'application.

Le programmeur démarre les instances lorsqu'il détermine que davantage d'instances sont nécessaires. Les requêtes de préchauffage peuvent apparaître dans les journaux même si elles sont désactivées, car le programmeur s'en sert pour démarrer des instances.

Notez que l'appel des requêtes de préchauffage n'est pas garanti. Dans certains cas, des requêtes de chargement sont envoyées à la place, par exemple s'il s'agit de la première instance démarrée ou en cas de forte augmentation du trafic. Cependant, si les requêtes de préchauffage sont activées, le système fera de son mieux pour envoyer les requêtes aux instances déjà préchauffées.

Pour activer les requêtes de préchauffage, ajoutez l'élément warmup sous la directive inbound_services dans le fichier app.yaml. Exemple :

inbound_services:
- warmup

Créer un gestionnaire

Créez un gestionnaire qui traitera les requêtes envoyées à /_ah/warmup. Ce gestionnaire doit exécuter toute logique de préchauffage nécessaire à votre application.


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