Hinweis: Java 8 hat das Ende des Supports am 31. Januar 2024 erreicht. Ihre vorhandenen Java 8-Anwendungen werden weiterhin ausgeführt und erhalten Traffic. App Engine kann jedoch die erneute Bereitstellung von Anwendungen blockieren, die Laufzeiten nach dem Enddatum des Supports verwenden. Wir empfehlen Ihnen, anhand der Richtlinien auf dieser Seite zur neuesten unterstützten Version von Java zu migrieren.
Durch die Migration zu den Java 11+-Laufzeiten, auch als Java-Laufzeiten der zweiten Generation bezeichnet, können Sie die neuesten Sprachfunktionen verwenden und Anwendungen erstellen, die portabler sind und idiomatischen Code nutzen.
Informationen zu Migrationsoptionen
Zur Reduzierung des Aufwands und der Komplexität der Laufzeitmigration können Sie mit der App Engine-Standardumgebung auf viele gebündelte Legacy-Dienste und -APIs wie Memcache in der Java-Laufzeit der zweiten Generation zugreifen. Ihre Java-Anwendung kann die gebündelten Dienst-APIs über das App Engine API-JAR aufrufen und auf die meisten Funktionen der Java 8-Laufzeitumgebung 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 Java. Für die gebündelten Dienste, die in Google Cloud nicht als separate Produkte verfügbar sind, wie Bildverarbeitung, Suche und Messaging, können Sie Drittanbieter oder andere Problemumgehungen verwenden.
Weitere Informationen zur Migration zu nicht gebündelten Diensten finden Sie unter Von gebündelten Diensten migrieren.
Je nachdem, ob Sie gebündelte Legacy-Dienste verwenden, gibt es einige Unterschiede bei der Ausführung der Laufzeitmigration:
Mit gebündelten Diensten zu Java 11+ migrieren | Zu Java 11+ ohne gebündelte Dienste migrieren |
---|---|
Mit der JAR-Datei der App Engine APIs auf gebündelte Dienste zugreifen | Optional können Sie empfohlene Google Cloud-Produkte oder Drittanbieterdienste verwenden. |
Verwenden Sie Abhängig von den Features der Anwendung müssen Sie möglicherweise zusätzliche YAML-Dateien konfigurieren. |
Verwenden Sie Abhängig von den Features der Anwendung müssen Sie möglicherweise zusätzliche YAML-Dateien konfigurieren. |
Anwendungen werden über Jetty bereitgestellt. Verwenden Sie das WAR-Format, um Ihre Anwendung zu verpacken. | Anwendungen werden mit Ihrem eigenen Server bereitgestellt. Verwenden Sie das JAR-Format, um Ihre Anwendung zu verpacken. Weitere Informationen zum Konvertieren Ihrer vorhandenen WAR-Datei in eine ausführbare JAR-Datei finden Sie unter WAR-Datei verpacken. |
Übersicht über den Migrationsprozess
Im Folgenden sind einige Änderungen aufgeführt, die Sie möglicherweise an Ihrer vorhandenen App Engine Java 8-Anwendung und Ihrem Bereitstellungsprozess vornehmen müssen, um die Java-Laufzeit der zweiten Generation zu verwenden:
- Google Cloud CLI herunterladen
- Migration vom eigenständigen App Engine-Maven-Plug-in zum gcloud CLI-basierten Maven-Plug-in oder zum gcloud CLI-basierten Gradle-Plug-in.
- Installieren Sie die App Engine API JAR, wenn Sie die gebündelten Legacy-Dienste verwenden.
Migrieren Sie Ihre XML-Dateien in die entsprechenden
yaml
-Dateien.
Hauptunterschiede zwischen den Java 8- und Java 11+-Laufzeiten
Im Folgenden finden Sie eine Zusammenfassung der Unterschiede zwischen den Java 8- und Java 11+-Laufzeiten in der App Engine-Standardumgebung:
Java 8-Laufzeit | Java 11+-Laufzeiten | |
---|---|---|
Serverbereitstellung | Für Sie über Jetty bereitgestellter Server | Wenn Ihre Anwendung die gebündelten Legacy-Dienste nicht verwendet, müssen Sie selbst einen Server bereitstellen.1 |
Gebündelte App Engine Legacy-Dienste | Bereitgestellt | Bereitgestellt |
Fähigkeit zur Verwendung von Cloud-Clientbibliotheken für Java | Ja | Ja |
Unterstützung von Sprachenerweiterungen und Systembibliotheken | Ja | Ja |
Externer Netzwerkzugriff | Ja | Ja |
Dateisystemzugriff | Lese- / Schreibzugriff auf /tmp
|
Lese- / Schreibzugriff auf /tmp
|
Sprachlaufzeit | Für App Engine geändert | Unveränderte Open-Source-Laufzeit |
Isolationsmechanismus | gVisor-basierte Container-Sandbox | gVisor-basierte Container-Sandbox |
Mit lokalem Entwicklungsserver testen | Unterstützt | Unterstützt |
Thread-Sicherheitskonfiguration | Kann in der Datei appengine-web.xml angegeben werden.
|
Kann nicht in den Konfigurationsdateien angegeben werden. Es wird davon ausgegangen, dass alle Apps threadsicher sind.3 |
Logging | Verwendet einen java.util.logging. ConsoleHandler , der in stderr schreibt und den Stream nach jedem Eintrag leert. |
Standardmäßiges Cloud Logging2 |
Unterstützung für DataNucleus-Plug-in 2.x | Unterstützt | Nicht unterstützt 4 |
Hinweise:
Wenn Ihre Anwendung keine gebündelten Legacy-Dienste verwendet, können die Java-Laufzeiten der zweiten Generation jedes Java-Framework ausführen, solange Sie einen Webserver verpacken. Dieser ist so konfiguriert, dass er auf HTTP-Anfragen auf dem Port antwortet, der durch die Umgebungsvariable
PORT
(empfohlen) oder auf Port 8080 angegeben wird. Beispiel: Die Java-Laufzeiten der zweiten Generation können eine Spring Boot Uber-JAR-Datei unverändert ausführen. Weitere Beispiele finden Sie im Abschnitt Framework-Flexibilität.Wenn Ihre Anwendung gebündelte Legacy-Dienste verwendet, stellt App Engine sie mithilfe von Jetty auf die gleiche Weise wie in der Java 8-Laufzeit bereit.
Das Logging in Java-Laufzeiten der zweiten Generation folgt dem Logging-Standard in Cloud Logging. In den Java-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 Java-Laufzeiten der zweiten Generation finden Sie in der Logging-Anleitung.
Zum Konfigurieren einer nicht threadsicheren Anwendung in der Java-Laufzeit derzeiten Generation legen Sie ähnlich wie bei der Einstellung von
<threadsafe>false</threadsafe>
in Java 8 entweder in derapp.yaml
-Datei oder in derappengine-web.xml
-Datei die maximale Gleichzeitigkeit auf 1 fest, wenn die gebündelten Legacy-Dienste verwendet werden.Google unterstützt die DataNucleus-Bibliothek in Laufzeiten der zweiten Generation nicht. Neuere Versionen von DataNucleus sind mit den in Java 8 verwendeten Versionen abwärtskompatibel. Für den Zugriff auf Datastore empfehlen wir die Clientbibliothek im Datastore-Modus oder die Java-Lösung Objectify (ab Version 6). Objectify ist eine Open-Source-API für Datastore, die eine höhere Abstraktionsebene bietet.
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 beim Anfrageheader
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.
Framework-Flexibilität
Die Java-Laufzeiten der zweiten Generation enthalten kein Web-Serving-Framework, es sei denn, Sie verwenden die gebündelten Legacy-Dienste. Dies bedeutet, dass Sie ein anderes Framework als ein Servlet-basiertes Framework verwenden können. Wenn Sie die gebündelten Legacy-Dienste verwenden, stellen die Java-Laufzeiten der zweiten Generation das Jetty-Web-Serving-Framework bereit.
Im Google Cloud GitHub-Repository gibt es hello world
-Beispiele, die gängige Java-Web-Frameworks verwenden:
XML-Dateien in YAML-Dateien migrieren
Die gcloud CLI unterstützt folgende Dateiformate nicht:
cron.xml
datastore-index.xml
dispatch.xml
queue.xml
Die folgenden Beispiele zeigen, wie Sie Ihre xml
-Dateien in yaml
-Dateien migrieren können.
Dateien automatisch migrieren
So migrieren Sie Ihre xml
-Dateien automatisch:
Sie benötigen die Version 226.0.0 oder höher der gcloud CLI. So führen Sie ein Update auf die neueste Version aus:
gcloud components update
Geben Sie für jede Datei, die Sie migrieren möchten, einen der folgenden Unterbefehle (
cron-xml-to-yaml
,datastore-indexes-xml-to-yaml
,dispatch-xml-to-yaml
,queue-xml-to-yaml
) und den Dateinamen an:gcloud beta app migrate-config queue-xml-to-yaml MY-QUEUE-XML-FILE.xml
Prüfen Sie manuell die konvertierte Datei, bevor Sie sie in der Produktionsumgebung bereitstellen.
Eine Beispielkonvertierung von
xml
zuyaml
finden Sie unter den Tabs Dateien manuell migrieren.
Dateien manuell migrieren
So migrieren Sie Ihre xml
-Dateien manuell in yaml
-Dateien:
cron.yaml
Erstellen Sie eine Datei cron.yaml
mit einem cron
-Objekt. Dieses muss wiederum Objekte jeweils mit den Feldern enthalten, die den <cron>
-Tag-Attributen in Ihrer cron.xml
-Datei entsprechen, wie unten gezeigt.
Konvertierte cron.yaml
-Datei:
cron:
- url: '/recache'
schedule: 'every 2 minutes'
description: 'Repopulate the cache every 2 minutes'
- url: '/weeklyreport'
schedule: 'every monday 08:30'
target: 'version-2'
timezone: 'America/New_York'
description: 'Mail out a weekly report'
Original cron.xml
-Datei:
<?xml version="1.0" encoding="UTF-8"?>
<cronentries>
<cron>
<url>/recache</url>
<description>Repopulate the cache every 2 minutes</description>
<schedule>every 2 minutes</schedule>
</cron>
<cron>
<url>/weeklyreport</url>
<description>Mail out a weekly report</description>
<schedule>every monday 08:30</schedule>
<timezone>America/New_York</timezone>
<target>version-2</target>
</cron>
</cronentries>
Weitere Informationen finden Sie in der Referenzdokumentation zu cron.yaml
.
dispatch.yaml
Erstellen Sie eine dispatch.yaml
-Datei mit einem dispatch
-Objekt. Dieses muss wiederum Objekte jeweils mit den Feldern enthalten, die den <dispatch>
-Tag-Attributen in Ihrer dispatch.xml
-Datei entsprechen, wie unten gezeigt.
Konvertierte dispatch.yaml
-Datei:
dispatch:
- url: '*/favicon.ico'
module: default
- url: 'simple-sample.uc.r.appspot.com/'
module: default
- url: '*/mobile/*'
module: mobile-frontend
Original dispatch.xml
-Datei:
<?xml version="1.0" encoding="UTF-8"?>
<dispatch-entries>
<dispatch>
<url>*/favicon.ico</url>
<module>default</module>
</dispatch>
<dispatch>
<url>simple-sample.uc.r.appspot.com/</url>
<module>default</module>
</dispatch>
<dispatch>
<url>*/mobile/*</url>
<module>mobile-frontend</module>
</dispatch>
</dispatch-entries>
Weitere Informationen finden Sie in der Referenzdokumentation zu dispatch.yaml
.
index.yaml
Erstellen Sie eine index.yaml
-Datei mit einem indexes
-Objekt. Dieses muss wiederum Objekte jeweils mit den Feldern enthalten, die den <datastore-index>
-Tag-Attributen in Ihrer datastore-indexes.xml
-Datei entsprechen, wie unten gezeigt.
Konvertierte index.yaml
-Datei:
indexes:
- ancestor: false
kind: Employee
properties:
- direction: asc
name: lastName
- direction: desc
name: hireDate
- ancestor: false
kind: Project
properties:
- direction: asc
name: dueDate
- direction: desc
name: cost
Original datastore-index.xml
-Datei:
<?xml version="1.0" encoding="utf-8"?>
<datastore-indexes
autoGenerate="true">
<datastore-index kind="Employee" ancestor="false">
<property name="lastName" direction="asc" />
<property name="hireDate" direction="desc" />
</datastore-index>
<datastore-index kind="Project" ancestor="false">
<property name="dueDate" direction="asc" />
<property name="cost" direction="desc" />
</datastore-index>
</datastore-indexes>
Weitere Informationen finden Sie in der Referenzdokumentation zu index.yaml
.
queue.yaml
Erstellen Sie eine queue.yaml
-Datei mit einem queue
-Objekt. Dieses muss wiederum Objekte jeweils mit den Feldern enthalten, die den <queue>
-Tag-Attributen in Ihrer queue.xml
-Datei entsprechen, wie unten gezeigt.
Konvertierte queue.yaml
-Datei:
queue:
- name: fooqueue
mode: push
rate: 1/s
retry_parameters:
task_retry_limit: 7
task_age_limit: 2d
- name: barqueue
mode: push
rate: 1/s
retry_parameters:
min_backoff_seconds: 10
max_backoff_seconds: 200
max_doublings: 0
Original queue.xml
-Datei:
<queue-entries>
<queue>
<name>fooqueue</name>
<rate>1/s</rate>
<retry-parameters>
<task-retry-limit>7</task-retry-limit>
<task-age-limit>2d</task-age-limit>
</retry-parameters>
</queue>
<queue>
<name>barqueue</name>
<rate>1/s</rate>
<retry-parameters>
<min-backoff-seconds>10</min-backoff-seconds>
<max-backoff-seconds>200</max-backoff-seconds>
<max-doublings>0</max-doublings>
</retry-parameters>
</queue>
<queue-entries>