Java 8-Laufzeitumgebung

Mit App Engine können Sie Webanwendungen erstellen, die die skalierbare Infrastruktur und Dienste von Google nutzen. App Engine führt Ihre Webanwendung mit einer Java 8-JVM aus. Zur Bearbeitung von Anfragen und zur Vorbereitung von Antworten in dieser Umgebung ruft App Engine die Servlet-Klassen Ihrer Anwendungen auf.

Die App Engine-Plattform bietet viele integrierte API-Dienste, die Ihr Code aufrufen kann. Außerdem kann Ihre Anwendung geplante Aufgaben konfigurieren, die in bestimmten Intervallen ausgeführt werden.

Java 8-Laufzeit für die Anwendung angeben

Damit Ihre Anwendung die Java  8-Laufzeit verwendet, fügen Sie der Datei appengine-web.xml die folgende Zeile hinzu:

<runtime>java8</runtime>

Die in der Google Cloud-Befehlszeile unter platform/google_appengine/google/appengine/tools/java/lib/impl/appengine-api.jar enthaltene Datei appengine-api.jar stellt die App Engine API für Java dar. Sie können auf diese Datei auch über das Maven-Repository zugreifen, in dem alle Versionen aufgelistet sind.

Sie wählen die von Ihrer Anwendung verwendete Version der API aus, wenn Sie diese JAR-Datei in das Verzeichnis WEB-INF/lib/ der Anwendung aufnehmen oder Maven zur Verwaltung der Abhängigkeiten verwenden. Wenn eine neue Version der Java-Laufzeitumgebung mit Änderungen veröffentlicht wird, die mit vorhandenen Anwendungen nicht kompatibel sind, trägt diese Umgebung eine neue Hauptversionsnummer.

Abhängigkeiten mit Maven verwalten

Sie können Maven verwenden, um alle Abhängigkeiten zu verwalten. Dieser pom.xml-Eintrag enthält beispielsweise die neueste App Engine API (Rappengine-api-1.0-sdk), die von Maven Central verfügbar ist:

<dependency>
    <groupId>com.google.appengine</groupId>
    <artifactId>appengine-api-1.0-sdk</artifactId>
    <version></version>
</dependency>

Sandbox

Die App Engine-Java-Laufzeit verteilt Anfragen für Anwendungen auf mehrere Webserver und verhindert somit, dass eine Anwendung eine andere beeinträchtigt. Eine App Engine-Anwendung darf nicht langsam reagieren. Eine an eine Anwendung gerichtete Webanfrage muss innerhalb des Zeitlimits der Anfrage verarbeitet werden. Prozesse, die dieses Antwortlimit überschreiten, werden beendet, um den Webserver nicht zu überlasten.

Das einzige Verzeichnis, in das Nutzer Dateien schreiben können, ist /tmp. Dateien in /tmp verbrauchen Arbeitsspeicher, der Ihrer Instanz zugeordnet ist. Die an diesem Ort gespeicherten Dateien sind nur für diese Instanz und nur für die Lebensdauer genau dieser Instanz verfügbar.

Die übliche Methode für Ihre Anwendung, Ressourcendateien abzurufen, besteht darin, die Dateien, auf die Sie angewiesen sind, unter WEB-INF zu verpacken und dann mit Class.getResource(), ServletContext.getResource() oder ähnlichen Methoden aus Ihrer Anwendung zu laden. Standardmäßig sind alle Dateien in der WAR "Ressourcendateien". Sie können Dateien aus diesem Satz mithilfe der Datei appengine-web.xml ausschließen.

Reihenfolge der JARs zum Laden der Klassen

Manchmal muss die Reihenfolge, in der JAR-Dateien nach Klassen gescannt werden, neu definiert werden, um Konflikte zwischen Klassennamen zu lösen. In diesen Fällen können Sie für bestimmte JAR-Dateien eine Ladepriorität festlegen, indem Sie ein Element <class-loader-config> mit Elementen von <priority-specifier> zur Datei appengine-web.xml hinzufügen. Beispiel:

<class-loader-config>
  <priority-specifier filename="mailapi.jar"/>
</class-loader-config>

Hiermit wird die JAR-Datei "mailapi.jar" als Erstes nach Klassen durchsucht und die Dateien im Verzeichnis war/WEB-INF/classes/ werden zurückgestellt.

Wenn Sie mehrere JAR-Dateien priorisieren, wird deren ursprüngliche Ladereihenfolge (in Bezug zueinander) verwendet. Die Reihenfolge der <priority-specifier>-Elemente selbst spielt also keine Rolle.

Threads

Mit der Java 8-Laufzeit können Sie Threads über die ThreadManager API von App Engine und die in Java integrierten APIs wie new Thread() erstellen. Wenn Sie App Engine APIs (com.google.appengine.api.*) aufrufen möchten, müssen Sie dies derzeit über einen Anfragethread oder einen Thread tun, der mit der ThreadManager API erstellt wurde.

Eine Anwendung kann

Wenn Sie einen ThreadPoolExecutor mit currentRequestThreadFactory() erstellen, muss shutdown() explizit aufgerufen werden, bevor die Servlet-Anfrage abgeschlossen ist. Andernfalls wird die Anfrage nicht abgeschlossen und der Anwendungsserver schließlich ausfallen. Beachten Sie, dass einige Bibliotheken ThreadPoolExecutors für Sie erstellen.

Eine Anwendung kann Operationen gegen den aktuellen Thread machen, z. B. thread.interrupt().

Jede Anfrage ist auf 50 gleichzeitige App Engine API-Anfragethreads beschränkt.

Wenn Sie mit Threads arbeiten, sollten Sie Objekte mit hoher Gleichzeitigkeit wie Executor und Runnable verwenden. Diese kümmern sich um viele der subtilen, aber wichtigen Details der Gleichzeitigkeit wie Interrupts sowie Planung und Verwaltung.

Die maximale Anzahl gleichzeitiger Hintergrundthreads, die von der App Engine API erstellt werden kann, liegt bei 10 Threads pro Instanz. (Dieses Limit gilt nicht für reguläre Java-Threads, die nicht mit der App Engine API in Zusammenhang stehen.)

Tools

Unterstützte IDEs

Cloud Tools for Eclipse fügt der Eclipse-IDE neue Projektassistenten und Debugging-Konfigurationen für App Engine-Projekte hinzu. Sie können die App Engine-Projekte aus Eclipse heraus in der Produktionsumgebung bereitstellen.

Mit Cloud Tools for IntelliJ können Sie App Engine-Anwendungen in IntelliJ IDEA ausführen und dort debuggen. Außerdem haben Sie die Möglichkeit, Ihre App Engine-Projekte in der Produktionsumgebung zu erstellen, ohne die IDE zu verlassen.

Unterstützte Buildtools

Mit den App Engine-Plug-ins für Apache Maven oder Gradle können Sie den Entwicklungsprozess beschleunigen:

Lokaler Entwicklungsserver

Während der Entwicklungs- und Testphase führt der Entwicklungsserver die Anwendung auf dem lokalen Computer aus. Der Server simuliert dabei die Datastore-Dienste. Der Entwicklungsserver erstellt auch die Konfiguration für Datenspeicherindizes anhand der Abfragen, die von der Anwendung während der Testphase durchgeführt werden.

Gleichzeitigkeit und Latenz

Die Latenz Ihrer Anwendung hat den größten Einfluss auf die Anzahl der Instanzen, die für die Verarbeitung Ihres Traffics erforderlich ist. Wenn Sie Anfragen schnell verarbeiten, kann eine einzelne Instanz viele Anfragen bewältigen.

Einzelthread-Instanzen können jeweils eine gleichzeitige Anfrage verarbeiten. Daher besteht ein direkter Zusammenhang zwischen der Latenz und der Anzahl der Anfragen, die pro Sekunde auf der Instanz verarbeitet werden können. Zum Beispiel entspricht eine Latenz von 10 ms 100 Anfragen pro Sekunde und pro Instanz.

Multithread-Instanzen können viele gleichzeitige Anfragen verarbeiten. Daher besteht ein direkter Zusammenhang zwischen der beanspruchten CPU und der Anzahl der Anfragen pro Sekunde.

Java-Anwendungen unterstützen gleichzeitige Anfragen, sodass eine einzelne Instanz neue Anfragen verarbeiten kann, während sie auf den Abschluss anderer Anfragen wartet. Durch die Gleichzeitigkeit wird die Anzahl der Instanzen, die Ihre Anwendung benötigt, erheblich reduziert. Allerdings müssen Sie Multithreading beim Entwurf Ihrer Anwendung integrieren.

Wenn beispielsweise eine B4-Instanz (ca. 2,4 GHz) 10 Mega-Prozessorzyklen pro Anfrage beansprucht, können Sie 240 Anfragen pro Sekunde und pro Instanz verarbeiten. Bei 100 Mega-Prozessorzyklen pro Anfrage werden 24 Anfragen pro Sekunde und pro Instanz erreicht. Diese Zahlen sind der Idealfall, aber in Bezug auf den erreichbaren Durchsatz auf einer Instanz recht realistisch.

App Engine-Java-Releases

Alle freigegebenen Artefakte, die mit Version 2.x.x beginnen, verwenden den Releasemechanismus Open Source. Freigegebene Artefakte, die mit Version 1.9.9xx oder früher beginnen, verwenden das interne Build-System. Weitere Informationen finden Sie im GitHub-Repository.

Umgebungsvariablen

Folgende Umgebungsvariablen werden durch die Laufzeit festgelegt:

Umgebungsvariable Beschreibung
GAE_APPLICATION ID der App Engine-Anwendung. Diese ID hat das Präfix „region code~”, z. B. „e~” für Anwendungen, die in Europa bereitgestellt werden.
GAE_DEPLOYMENT_ID ID der aktuellen Bereitstellung.
GAE_ENV App Engine-Umgebung. Legen Sie standard fest.
GAE_INSTANCE ID der Instanz, auf der Ihr Dienst gerade ausgeführt wird.
GAE_RUNTIME Laufzeit, die in der Datei app.yaml angegeben ist.
GAE_SERVICE Dienstname, der in der Datei app.yaml angegeben ist. Wenn kein Dienstname angegeben ist, wird als Wert default festgelegt.
GAE_VERSION Aktuelle Versionsbezeichnung Ihres Dienstes.
GOOGLE_CLOUD_PROJECT Google Cloud-Projekt-ID, die der Anwendung zugeordnet ist.
PORT Port, der HTTP-Anfragen empfängt.

Sie können zusätzliche Umgebungsvariablen in Ihrer app.yaml-Datei definieren. Die oben genannten Werte können jedoch nicht überschrieben werden.