Migrer de Go 1.11 vers le dernier environnement d'exécution Go

La migration vers un environnement d'exécution Go de deuxième génération compatible vous permet d'utiliser des fonctionnalités de langage à jour et de créer des applications plus portables, avec du code idiomatique.

Modifications apportées aux environnements d'exécution de deuxième génération

Si vous migrez vers un environnement d'exécution Go de deuxième génération compatible, vous devez prendre en compte les différences suivantes entre les environnements d'exécution de première et de deuxième génération :

  • Pour réduire la complexité et les efforts liés à la migration, l'environnement standard App Engine vous permet d'accéder à de nombreux anciens services et API groupés dans les environnements d'exécution de deuxième génération, tels que Memcache. Votre application Go de deuxième génération peut appeler les API de services groupés à l'aide du SDK App Engine pour Go et accéder à la plupart des fonctionnalités de l'environnement d'exécution Go 1.11.

    Vous avez également la possibilité d'utiliser des produits Google Cloud qui offrent des fonctionnalités similaires aux anciens services groupés. Ces produits Google Cloud fournissent des bibliothèques clientes cloud idiomatiques pour Go. Pour les services groupés qui ne sont pas disponibles séparément dans Google Cloud, tels que le traitement d'image, la recherche et les messages, vous pouvez faire appel à des fournisseurs tiers ou à d'autres solutions.

    Pour en savoir plus sur la migration vers des services non groupés, consultez la page Effectuer la migration à partir de services groupés.

  • Le comportement de certains éléments du fichier de configuration app.yaml a été modifié. Pour en savoir plus, consultez la section Modifications apportées au fichier app.yaml.

  • La journalisation dans l'environnement d'exécution de deuxième génération suit la norme de journalisation de Cloud Logging. Dans les environnements d'exécution de deuxième génération, les journaux d'applications ne sont plus groupés avec les journaux de requêtes, mais sont séparés dans des enregistrements différents. Pour en savoir plus sur la lecture et l'écriture de journaux dans les environnements d'exécution de deuxième génération, consultez le guide de journalisation.

Différences d'utilisation de la mémoire

Les environnements d'exécution de deuxième génération présentent une utilisation de référence de la mémoire plus élevée que les environnements d'exécution de première génération. Cela est dû à plusieurs facteurs, tels que les différentes versions d'image de base et les différences dans la manière dont les deux générations calculent l'utilisation de la mémoire.

Dans les environnements d'exécution de deuxième génération, l'utilisation de la mémoire des instances est calculée comme la somme de la mémoire utilisée par un processus d'application et du nombre de fichiers d'application mis en cache de manière dynamique en mémoire. Pour éviter que les applications qui utilisent beaucoup de mémoire ne provoquent des arrêts d'instance en raison du dépassement des limites de mémoire, effectuez une mise à niveau vers une classe d'instance plus grande avec plus de mémoire.

Différences d'utilisation du processeur

Les environnements d'exécution de deuxième génération peuvent constater une utilisation de référence plus élevée lors du démarrage à froid de l'instance. Selon la configuration du scaling d'une application, cela peut avoir des effets secondaires inattendus, tels qu'un nombre d'instances plus élevé que prévu si une application est configurée pour évoluer en fonction de l'utilisation du processeur. Pour éviter ce problème, examinez et testez les configurations de scaling des applications pour vous assurer que le nombre d'instances est acceptable.

Différences au niveau des en-têtes de requête

Les environnements d'exécution de première génération permettent de transmettre à l'application des en-têtes de requêtes comportant des traits de soulignement (par exemple, X-Test-Foo_bar). Les environnements d'exécution de deuxième génération introduisent Nginx dans l'architecture hôte. Suite à cette modification, les environnements d'exécution de deuxième génération sont configurés pour supprimer automatiquement les en-têtes comportant des traits de soulignement (_). Pour éviter les problèmes liés à l'application, évitez d'utiliser des traits de soulignement dans les en-têtes de requête de l'application.

Modifications apportées au fichier app.yaml

Le comportement de certains éléments du fichier de configuration app.yaml a été modifié :

Élément Type de modification Description
app_engine_apis Obligatoire pour les applications utilisant d'anciens services groupés Doit être défini sur true si vous souhaitez accéder aux anciens services groupés pour les environnements d'exécution de deuxième génération.
login Compatible si app_engine_apis est true Si vous n'utilisez pas les anciens services groupés pour les environnements d'exécution de deuxième génération, appliquez d' autres méthodes d'authentification des utilisateurs.
runtime Modifiée Modifiez l'élément runtime pour spécifier un environnement d'exécution de deuxième génération.

Pour en savoir plus, consultez la documentation de référence sur app.yaml.

Créer un package main

Votre service doit inclure une instruction package main dans au moins l'un des fichiers sources. S'il utilise le package google.golang.org/appengine, il doit inclure un appel à appengine.Main().

Écrire un package "main"

Si votre service ne contient pas encore de package main, ajoutez l'instruction package main et rédigez une fonction main(). La fonction main() doit au minimum :

  • lire la variable d'environnement PORT et appeler la fonction http.ListenAndServe() :

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

Enregistrer les gestionnaires HTTP

Vous pouvez enregistrer vos gestionnaires HTTP en choisissant une des options suivantes :

  • La méthode privilégiée consiste à déplacer manuellement tous les appels http.HandleFunc() de vos packages vers la fonction main() de votre package main.
  • Vous pouvez également importer les packages de l'application dans votre package main, en veillant à ce que chaque fonction init() contenant des appels adressés à http.HandleFunc() s'exécute au démarrage.

    Vous pouvez trouver tous les packages qui utilisent l'appel http.HandleFunc() à l'aide du script bash suivant, puis copier le résultat dans le bloc import de votre package main :

    gp=$(go env GOPATH) && p=$(pwd) && pkg=${p#"$gp/src/"} && find . -name "*.go" | xargs grep "http.HandleFunc" --files-with-matches | grep -v vendor/ | grep -v '/main.go' | sed "s#\./\(.*\)/[^/]\+\.go#\t_ \"$pkg/\1\"#" | sort | uniq
    

Structurer les fichiers

Go exige que chaque package dispose de son propre répertoire. Vous pouvez indiquer à App Engine où se trouve votre package main en utilisant main: dans le fichier app.yaml de votre projet. Par exemple, si votre application possédait la structure de fichiers suivante :

myapp/
├── app.yaml
├── foo.go
├── bar.go
└── web/
    └── main.go

Votre fichier app.yaml contiendrait :

main: ./web # Relative filepath to the directory containing your main package.

Pour plus d'informations sur l'option main, consultez la documentation de référence sur app.yaml.

Déplacer des fichiers vers GOPATH

Localisez votre variable d'environnement GOPATH à l'aide de la commande suivante :

go env GOPATH

Déplacez tous les fichiers et importations pertinents vers GOPATH. Si vous utilisez des importations relatives, telles que import ./guestbook, mettez-les à jour pour qu'elles utilisent le chemin complet : import github.com/example/myapp/guestbook.