Von Go 1.11 zur neuesten Go-Laufzeit migrieren

Die Migration zu einer unterstützten Go-Laufzeit der zweiten Generation bietet Ihnen die Möglichkeit, aktuelle Sprachfunktionen zu verwenden und mit idiomatischem Code portablere Anwendungen zu erstellen.

Änderungen an den Laufzeiten der zweiten Generation

Wenn Sie zu einer unterstützten Go-Laufzeit der zweiten Generation migrieren, müssen Sie die folgenden Unterschiede zwischen den Laufzeiten der ersten und zweiten Generation beachten:

  • Zur Reduzierung des Aufwands und der Komplexität der Laufzeitmigration können Sie mit der App Engine-Standardumgebung auf viele der gebündelte Legacy-Dienste und -APIs in der Laufzeit der zweiten Generation zugreifen wie z. B. Memcache. Ihre Go-Anwendung der zweiten Generation kann über das App Engine SDK für Go die gebündelten Dienst-APIs aufrufen und auf die meisten Features der Go 1.11-Laufzeit zugreifen.

    Sie können auch Google Cloud-Produkte verwenden, die vergleichbare Funktionen wie die gebündelten Legacy-Dienste bereitstellen. Diese Google Cloud-Produkte bieten idiomatische Cloud-Clientbibliotheken für Go. Für die gebündelten Dienste, die in Google Cloud nicht als eigenständige Produkte verfügbar sind, wie Bildverarbeitung, Suche oder Messaging, können Sie Drittanbieter oder andere Behelfslösungen verwenden.

    Weitere Informationen zur Migration zu nicht gebündelten Diensten finden Sie unter Von gebündelten Diensten migrieren.

  • Das Verhalten einiger Elemente in der Konfigurationsdatei app.yaml wurde geändert: Weitere Informationen finden Sie unter Änderungen an der Datei app.yaml.

  • Das Logging in der Laufzeit der zweiten Generation folgt dem Logging-Standard in Cloud Logging. In den Laufzeiten der zweiten Generation werden Anwendungslogs nicht mehr mit den Anfragelogs gebündelt, sondern in verschiedenen Einträgen getrennt. Weitere Informationen zum Lesen und Schreiben von Logs in Laufzeiten der zweiten Generation finden Sie in der Logging-Anleitung.

Unterschiede bei der Arbeitsspeichernutzung

Laufzeiten der zweiten Generation haben eine höhere Referenz für die Arbeitsspeichernutzung im Vergleich zu Laufzeiten der ersten Generation. Dies ist auf mehrere Faktoren zurückzuführen, z. B. unterschiedliche Basis-Image-Versionen und Unterschiede bei der Berechnung der Arbeitsspeichernutzung durch die beiden Generationen.

Laufzeiten der zweiten Generation berechnen die Arbeitsspeichernutzung der Instanz als Summe von dem, was von einem Anwendungsprozess verwendet wird, und der Anzahl der Anwendungsdateien, die dynamisch im Arbeitsspeicher zwischengespeichert werden. Führen Sie ein Upgrade auf eine größere Instanzklasse mit mehr Arbeitsspeicher durch, um zu vermeiden, dass es bei arbeitsspeicherintensiven Anwendungen aufgrund des Überschreitens von Arbeitsspeicherlimits zum Herunterfahren von Instanzen kommt.

Unterschiede bei der CPU-Auslastung

Laufzeiten der zweiten Generation können beim Kaltstart von Instanzen eine höhere Referenz der CPU-Auslastung aufweisen. Abhängig von der Skalierungskonfiguration einer Anwendung kann dies unbeabsichtigte Nebenwirkungen haben, z. B. eine höhere Anzahl von Instanzen als erwartet, wenn eine Anwendung für die Skalierung basierend auf der CPU-Auslastung konfiguriert ist. Überprüfen und testen Sie die Konfigurationen der Anwendungsskalierung, damit die Anzahl der Instanzen akzeptabel ist, um dieses Problem zu vermeiden.

Unterschiede bei Anfrageheadern

Laufzeiten der ersten Generation ermöglichen, dass Anfrageheader mit Unterstrichen (z. B. X-Test-Foo_bar) an die Anwendung weitergeleitet werden. Laufzeiten der zweiten Generation führen Nginx in die Hostarchitektur ein. Aufgrund dieser Änderung werden Laufzeiten der zweiten Generation so konfiguriert, dass Header mit Unterstrichen (_) automatisch entfernt werden. Vermeiden Sie die Verwendung von Unterstrichen in Anwendungsanfrageheadern, um Anwendungsprobleme zu vermeiden.

Änderungen an der Datei app.yaml

Das Verhalten einiger Elemente in der Konfigurationsdatei app.yaml wurde geändert:

Element Änderungstyp Beschreibung
app_engine_apis Erforderlich für Apps, die gebündelte Legacy-Dienste verwenden Muss auf true gesetzt werden, wenn Sie auf die gebündelten Legacy-Dienste für die Laufzeiten der zweiten Generation zugreifen möchten.
login Unterstützt, wenn für app_engine_apis der Wert true gilt. Wenn Sie keine gebündelten Legacy-Dienste für die Laufzeiten der zweiten Generation verwenden, können Sie diese alternativen Methoden zur Authentifizierung von Nutzern verwenden.
runtime Geändert Ändern Sie das Element runtime, um eine Laufzeit der zweiten Generation anzugeben.

Weitere Informationen finden Sie in der Referenz zu app.yaml.

main-Paket erstellen

Ihr Dienst muss in mindestens einer Quelldatei eine package main-Anweisung enthalten. Alternativ können Sie einen Aufruf von appengine.Main() hinzufügen, wenn Ihr Dienst das Paket google.golang.org/appengine verwendet.

main-Paket schreiben

Wenn Ihr Dienst noch kein main-Paket enthält, fügen Sie die Anweisung package main hinzu und schreiben Sie eine main()-Funktion. Die Funktion main() muss mindestens:

  • Die Umgebungsvariable PORT lesen und die Funktion http.ListenAndServe() aufrufen:

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

HTTP-Handler registrieren

Wählen Sie eine der folgenden Optionen, mit denen sich HTTP-Handler registrieren lassen:

  • Die bevorzugte Methode besteht darin, alle http.HandleFunc()-Aufrufe von Ihren Paketen manuell in die main()-Funktion in Ihrem main-Paket zu verschieben.
  • Alternativ können Sie die Pakete Ihrer Anwendung in das main-Paket importieren. Bei dieser Vorgehensweise müssen Sie gewährleisten, dass jede init()-Funktion, die Aufrufe von http.HandleFunc() enthält, beim Start ausgeführt wird.

    Sie können alle Pakete, die den http.HandleFunc()-Aufruf verwenden, mit dem folgenden Bash-Skript finden und die Ausgabe in den import-Block Ihres main-Pakets kopieren:

    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
    

Dateien strukturieren

Go erfordert, dass jedes Paket über ein eigenes Verzeichnis verfügt. Sie können App Engine mitteilen, wo sich Ihr main-Paket befindet, indem Sie main: in der app.yaml-Datei Ihres Projekts verwenden. Beispiel: Wenn die Dateistruktur Ihrer Anwendung so aussieht:

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

Hätte Ihre app.yaml-Datei Folgendes:

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

Weitere Informationen zum Flag main finden Sie in der app.yaml-Referenz.

Dateien in GOPATH verschieben

Ihren GOPATH finden Sie mit dem folgenden Befehl:

go env GOPATH

Verschieben Sie alle relevanten Dateien und Importe in GOPATH. Wenn Sie relative Importe wie import ./guestbook verwenden, aktualisieren Sie Ihre Importe, um den vollständigen Pfad zu verwenden: import github.com/example/myapp/guestbook.