Anfrageverarbeitung

Regions-ID

REGION_ID ist ein abgekürzter Code, den Google anhand der Region zuweist, die Sie beim Erstellen Ihrer Anwendung ausgewählt haben. Der Code bezieht sich nicht auf ein Land oder eine Provinz, auch wenn einige Regions-IDs häufig verwendeten Länder- und Provinzcodes ähneln können. Das Einbinden von REGION_ID.r in App Engine-URLs ist für vorhandene Anwendungen optional und wird bald für alle neuen Anwendungen erforderlich sein.

Für einen reibungslosen Übergang wird App Engine nach und nach für die Verwendung von Regions-IDs aktualisiert. Wenn Ihr Google Cloud-Projekt noch nicht aktualisiert wurde, wird für Ihre Anwendung keine Regions-ID angezeigt. Da die ID für vorhandene Anwendungen optional ist, müssen Sie keine URLs aktualisieren oder andere Änderungen vornehmen, wenn die Regions-ID für Ihre vorhandenen Anwendungen verfügbar wird.

Hier finden Sie weitere Informationen zu Regions-IDs.

In diesem Dokument wird beschrieben, wie Ihre App Engine-Anwendung Anfragen empfängt und Antworten sendet. Weitere Informationen finden Sie in der Referenz zu Anfrageheadern und Antworten.

Wenn Ihre Anwendung Dienste verwendet, können Sie Anfragen an einen bestimmten Dienst oder eine bestimmte Version dieses Dienstes richten. Weitere Informationen zur Adressierbarkeit von Diensten finden Sie unter Anfragenrouting.

Verarbeitung von Anfragen

Ihre Anwendung ist für den Start eines Webservers und die Verarbeitung von Anfragen zuständig. Sie können jedes Webframework verwenden, das für Ihre Entwicklungssprache verfügbar ist.

Wenn App Engine eine Webanfrage für die Anwendung empfängt, wird das Servlet aufgerufen, das der URL entspricht, wie in der Datei web.xml der Anwendung im Verzeichnis WEB-INF/ beschrieben. Die API-Spezifikationen für Java-Servlet 2.5 oder 3.1 werden unterstützt, um dem Servlet die Anfragedaten zu senden und die Antwortdaten zu akzeptieren.

App Engine führt mehrere Instanzen Ihrer Anwendung aus. Jede Instanz hat ihren eigenen Webserver zur Verarbeitung von Anfragen. Jede Anfrage kann an jede Instanz weitergeleitet werden. Aufeinanderfolgende Anfragen von einem Nutzer werden daher nicht unbedingt an dieselbe Instanz gesendet. Die Anzahl der Instanzen kann automatisch angepasst werden, wenn sich der Traffic ändert.

Standardmäßig verarbeitet jeder Webserver jeweils immer nur einen einzigen Request. Wenn Sie parallel mehrere Anfragen an jeden Webserver senden möchten, kennzeichnen Sie die Anwendung als threadsafe. Dazu fügen Sie der Datei appengine-web.xml das Element <threadsafe>true</threadsafe> hinzu.

Die folgende Beispiel-Servlet-Klasse zeigt im Browser des Nutzers eine einfache Nachricht an.

// With @WebServlet annotation the webapp/WEB-INF/web.xml is no longer required.
@WebServlet(name = "requests", description = "Requests: Trivial request", urlPatterns = "/requests")
public class RequestsServlet extends HttpServlet {

  @Override
  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    resp.setContentType("text/plain");
    resp.getWriter().println("Hello, world");
  }
}

Kontingente und Limits

App Engine weist Ihrer Anwendung automatisch Ressourcen zu, wenn der Traffic zunimmt. Dies ist jedoch an folgende Einschränkungen gebunden:

  • App Engine reserviert Kapazitäten für die automatische Skalierung von Anwendungen mit niedriger Latenz, die Anfragen in weniger als einer Sekunde beantworten. Bei Anwendungen, die bei einem hohen Anfrageaufkommen eine sehr hohe Latenz von beispielsweise über einer Sekunde pro Anfrage haben, ist Silber-, Gold- oder Platin-Support erforderlich. Kunden mit einer dieser Supportstufen können bei ihrem zuständigen Supportmitarbeiter höhere Durchsatzlimits anfordern.

  • Bei stark an CPUs gebundenen Anwendungen kann die Latenz auch geringfügig höher sein, um Ressourcen gemeinsam mit anderen Anwendungen effizient auf denselben Servern zu nutzen. Anfragen nach statischen Dateien sind von diesen Latenzbeschränkungen ausgenommen.

Alle eingehenden Anfragen an die Anwendung werden auf das Limit für Anfragen angerechnet. Die als Antwort auf eine Anfrage gesendete Daten werden auf das Limit Ausgehende Bandbreite (kostenpflichtig) angerechnet.

Sowohl HTTP- als auch (sichere) HTTPS-Requests werden auf die Limits Requests, Eingehende Bandbreite (kostenpflichtig) und Ausgehende Bandbreite (kostenpflichtig) angerechnet. In der Cloud Console werden auf der Seite "Kontingentdetails" zu Informationszwecken außerdem die Werte für Sichere Anfragen, Sichere eingehende Bandbreite und Sichere ausgehende Bandbreite als separate Werte angezeigt. In diese Werte fließen nur HTTPS-Anfragen ein. Weitere Informationen finden Sie auf der Seite Kontingente.

Die folgenden Limits gelten speziell für die Verwendung von Anfrage-Handlern:

Limit Wert
Größe der Anfrage 32 MB
Antwortgröße 32 MB
Zeitüberschreitung bei Anfrage hängt von der Art der Skalierung ab, die Ihre Anwendung verwendet
Maximale Gesamtzahl Dateien (Anwendungsdateien und statische Dateien) 10.000 insgesamt
1.000 pro Verzeichnis
Maximale Größe einer Anwendungsdatei 32 MB
Maximale Größe einer statischen Datei 32 MB
Maximale Gesamtgröße aller Anwendungsdateien und statischen Dateien Das erste 1 GB ist kostenlos
0,026 $ pro GB pro Monat nach dem ersten GB

Antwortlimits

Dynamische Antworten sind auf eine Größe von 32 MB beschränkt. Wenn ein Skript-Handler eine Antwort generiert, die diesen Grenzwert überschreitet, sendet der Server eine leere Antwort mit dem Statuscode 500 ("Interner Serverfehler") zurück. Diese Beschränkung gilt nicht für Antworten, die Daten aus dem Blobstore oder aus Cloud Storage bereitstellen.

Anfrageheader

Eine eingehende HTTP-Anfrage enthält die HTTP-Header, die vom Client gesendet werden. Einige Header werden aus Sicherheitsgründen von zwischengeschalteten Proxys bereinigt oder berichtigt, bevor sie die Anwendung erreichen.

Weitere Informationen finden Sie in der Referenz zu Anfrageheadern.

Zeitlimit für Anfragen setzen

App Engine ist für Anwendungen mit kurzlebigen Anfragen optimiert, die in der Regel wenige Hundert Millisekunden in Anspruch nehmen. Effiziente Anwendungen antworten schnell auf die meisten Anfragen. Bei Anwendungen, die nicht schnell antworten, ist es unwahrscheinlich, dass sie mit der Infrastruktur von App Engine optimal skalieren.

Alle Anfragen an Ihre Anwendung müssen innerhalb des maximalen Zeitlimits für Anfragen eine Antwort zurückgeben. Wenn die Anwendung innerhalb dieses Zeitlimits keine Antwort zurückgibt, unterbricht App Engine den Anfrage-Handler. Die Java-Laufzeitumgebung unterbricht das Servlet durch Auslösen einer com.google.apphosting.api.DeadlineExceededException. Wenn kein Anfrage-Handler vorhanden ist, um die Ausnahme zu erfassen, wird von der Laufzeitumgebung ein HTTP-500-Serverfehler an den Client zurückgegeben.

Wenn es einen Anfrage-Handler gibt und die DeadlineExceededException abgefangen wird, gibt die Laufzeitumgebung dem Anfrage-Handler Zeit (weniger als eine Sekunde), um eine benutzerdefinierte Antwort vorzubereiten. Wenn der Anfrage-Handler nach dem Auslösen der Ausnahme mehr als eine Sekunde benötigt, um eine entsprechende Antwort vorzubereiten, wird der Fehler HardDeadlineExceededError ausgelöst.

Sowohl DeadlineExceededExceptions als auch HardDeadlineExceededErrors haben eine erzwungene Beendigung der Anfrage und das Anhalten der Instanz zur Folge.

Die Anwendung kann com.google.apphosting.api.ApiProxy importieren und ApiProxy.getCurrentEnvironment().getRemainingMillis() aufrufen, um herauszufinden, wie viel Zeit bis zum Ende der Frist verbleibt. Dies ist nützlich, wenn geplant ist, dass die Anwendung mit einer Aufgabe beginnt, die zu viel Zeit in Anspruch nehmen könnte. Wenn beispielsweise bekannt ist, dass die Verarbeitung einer Arbeitseinheit fünf Sekunden dauert, von getRemainingMillis() jedoch ein kürzerer Zeitraum zurückgegeben wird, wäre es kaum sinnvoll, mit dieser Arbeitseinheit zu beginnen.

Antworten

App Engine ruft das Servlet mit einem Anfrageobjekt und einem Antwortobjekt auf und wartet auf die Rückgabe des ausgefüllten Antwortobjekts. Wenn das Servlet antwortet, werden die Daten des Antwortobjekts an den Nutzer gesendet.

Für die von Ihnen generierte Antwort gelten Größenbeschränkungen und die Antwort kann geändert werden, bevor sie an den Client zurückgegeben wird.

Weitere Informationen finden Sie in der Referenz zu Antworten auf Anfragen.

Streamingantworten

App Engine unterstützt keine Streamingantworten, bei denen Daten in inkrementellen Blöcken an den Client gesendet werden, während eine Anfrage verarbeitet wird. Alle Daten aus Ihrem Code werden wie oben beschrieben erfasst und in einer einzigen HTTP-Antwort gesendet.

Antwortkomprimierung

App Engine versucht, komprimierte (gzip-)Inhalte für Clients bereitzustellen, die diese unterstützen. Um festzustellen, ob Inhalte komprimiert werden sollten, geht App Engine beim Empfang einer Anfrage so vor:

  1. Durch Aufrufen der Header Accept-Encoding und User-Agent in der Anfrage wird geprüft, ob der Client komprimierte Antworten zuverlässig empfangen kann. Durch diese Methode werden einige bekannte Fehler vermieden, die in gängigen Browsern mit gzip-Inhalten auftreten können.

  2. Durch Aufrufen des Headers Content-Type, den Sie für den Antwort-Handler konfiguriert haben, wird geprüft, ob die Komprimierung als Methode geeignet ist. Im Allgemeinen eignet sich eine Komprimierung für textbasierte Inhaltstypen und nicht für binäre Inhaltstypen.

Wichtige Hinweise:

  • Ein Client kann erzwingen, dass textbasierte Inhaltstypen komprimiert werden. Dazu muss für die Anfrageheader Accept-Encoding und User-Agent der Wert gzip festgelegt werden.

  • Wenn gzip nicht im Header der Anfrage Accept-Encoding enthalten ist, komprimiert App Engine die Antwortdaten nicht.

  • Das Google Front-End speichert Antworten von statischen App Engine-Datei- und Verzeichnis-Handlern im Cache. Abhängig von verschiedenen Faktoren, z. B. welche Art von Antwortdaten zuerst im Cache gespeichert wird, welche Vary-Header Sie in der Antwort angegeben haben und welche Header in der Anfrage enthalten sind, kann ein Client möglicherweise eine Anfrage für komprimierte Daten stellen, aber unkomprimierte Daten empfangen und umgekehrt. Weitere Informationen finden Sie unter Antwort-Caching.

Antwort-Caching

Das Google Front-End und möglicherweise der Browser des Nutzers sowie andere zwischengeschaltete Proxyserver für das Caching speichern die Antworten Ihrer Anwendung gemäß den Standard-Caching-Headern, die Sie in der Antwort angeben. Sie können diese Antwortheader entweder über Ihr Framework, direkt in Ihrem Code oder über statische Datei- und Verzeichnis-Handler von App Engine festlegen.

Im Google Front-End ist der Cache-Schlüssel die vollständige URL der Anfrage.

Statische Inhalte im Cache speichern

Damit Clients immer aktualisierte statische Inhalte empfangen, sobald sie veröffentlicht werden, empfehlen wir, statische Inhalte aus versionierten Verzeichnissen wie css/v1/styles.css bereitzustellen. Das Google Front-End führt die Validierung des Caches (seine Prüfung auf aktualisierte Inhalte) erst aus, wenn der Cache abläuft. Auch nach Ablauf des Cache wird der Cache erst aktualisiert, wenn sich der Inhalt der Anfrage-URL ändert.

Die folgenden Antwortheader, die Sie in appengine-web.xml festlegen können, haben Einfluss darauf, wie und wann das Front-End von Google Inhalte im Cache speichert:

  • Für Cache-Control muss der Wert public festgelegt sein, damit das Google Front-End den Inhalt im Cache speichert. Wenn Sie diesen Header nicht in appengine-web.xml festlegen, fügt App Engine ihn automatisch allen Antworten hinzu, die von einem statischen Datei- oder Verzeichnis-Handler verarbeitet werden. Weitere Informationen finden Sie unter Hinzugefügte oder ersetzte Header.

  • Vary: Damit der Cache basierend auf Headern, die in der Anfrage gesendet werden, unterschiedliche Antworten für eine URL zurückgeben kann, legen Sie im Vary-Anfrageheader einen oder mehrere der folgenden Werte fest: Accept, Accept-Encoding, Origin oder X-Origin

    Aufgrund einer potenziell hohen Kardinalität werden Daten für andere Vary-Werte nicht im Cache gespeichert.

    Beispiel:

    1. Sie geben den folgenden Antwortheader an:

      Vary: Accept-Encoding

    2. Ihre Anwendung erhält eine Anfrage mit dem Header Accept-Encoding: gzip. App Engine gibt eine komprimierte Antwort zurück und das Google Front-End speichert die mit gzip komprimierte Version der Antwortdaten im Cache. Alle nachfolgenden Anfragen für diese URL, die den Header Accept-Encoding: gzip enthalten, empfangen die mit gzip komprimierten Daten aus dem Cache, bis der Cache ungültig wird (weil sich der Inhalt nach Ablauf des Caches ändert).

    3. Ihre Anwendung erhält eine Anfrage ohne den Header Accept-Encoding. App Engine gibt eine unkomprimierte Antwort zurück und das Google Front-End speichert die unkomprimierte Version der Antwortdaten im Cache. Alle nachfolgenden Anfragen für diese URL, die den Header Accept-Encoding nicht enthalten, empfangen die komprimierten Daten aus dem Cache, bis der Cache ungültig wird.

    Wenn Sie keinen Vary-Antwortheader festlegen, erstellt das Google Front-End einen einzelnen Cache-Eintrag für die URL und verwendet ihn für alle Anfragen, unabhängig von den Headern in der Anfrage. Beispiel:

    1. Sie geben den Antwortheader Vary: Accept-Encoding nicht an.
    2. Eine Anfrage enthält den Header Accept-Encoding: gzip und die mit gzip komprimierte Version der Antwortdaten wird im Cache gespeichert.
    3. Eine zweite Anfrage enthält den Header Accept-Encoding: gzip nicht. Da der Cache jedoch eine mit gzip komprimierte Version der Antwortdaten enthält, wird die Antwort auch dann mit gzip komprimiert, wenn der Client nicht komprimierte Daten angefordert hat.

Die Header in der Anfrage haben auch Auswirkungen auf das Caching:

  • Wenn die Anfrage einen Authorization-Header enthält, werden die Inhalte vom Google Front-End nicht im Cache gespeichert.

Cache-Ablauf

Die Caching-Header, die den Antworten durch statische Datei- und Verzeichnis-Handler von App Engine hinzugefügt werden, weisen Clients und Webproxys wie das Google Front-End standardmäßig an, den Cache nach 10 Minuten ablaufen zu lassen.

Nachdem eine Datei mit einer bestimmten Ablaufzeit gesendet wurde, ist es im Allgemeinen nicht möglich, sie aus Webproxy-Caches zu löschen, auch wenn der Nutzer seinen eigenen Browser-Cache löscht. Caches werden nicht zurückgesetzt, wenn Sie eine neue Version der Anwendung bereitstellen. Falls Sie also jemals vorhaben, eine statische Datei zu ändern, sollte diese eine kurze Ablaufzeit von weniger als einer Stunde haben. In der Regel kann die Standardablaufzeit von 10 Minuten übernommen werden.

Sie können die Standardablaufzeit für alle statischen Datei- und Verzeichnis-Handler ändern. Geben Sie dazu in Ihrer Datei appengine-web.xml das Element default_expiration an. Zum Festlegen bestimmter Ablaufzeiten für einzelne Handler legen Sie das Element expiration innerhalb des Handler-Elements in Ihrer Datei appengine-web.xml fest.

Der Wert, den Sie für die Ablaufzeit der Elemente angeben, wird zum Festlegen der HTTP-Antwortheader Cache-Control und Expires verwendet.

Logging

Ihre Anwendung kann mit java.util.logging.Logger Informationen in die Anwendungslogs schreiben. Die Logdaten für Ihre Anwendung können Sie in der Cloud Console über Cloud Logging einsehen. Jeder protokollierten Anfrage wird eine Anfrage-ID zugewiesen, eine global eindeutige Kennung, die auf der Startzeit der Anfrage beruht. Die Cloud Console erkennt die Logebenen der Klasse Logger und zeigt Nachrichten interaktiv auf unterschiedlichen Ebenen an.

Alles, was vom Servlet in den Standardausgabestream (System.out) und Standardfehlerstream (System.err) geschrieben wird, wird von App Engine erfasst und in den Anwendungslogs aufgezeichnet. In den Standardausgabestream geschriebene Zeilen werden auf der Ebene "INFO" protokolliert, in den Standardfehlerstream geschriebene Zeilen auf der Ebene "WARNING". Es kann jedes Logging-Framework genutzt werden, das Ausgabe- oder Fehlerstreams protokolliert (z. B. log4j). Für eine detailliertere Steuerung der Anzeige der Logebene in der Cloud Console muss das Logging-Framework jedoch einen java.util.logging-Adapter verwenden.

// With @WebServlet annotation the webapp/WEB-INF/web.xml is no longer required.
@WebServlet(
    name = "RequestLogging",
    description = "Requests: Logging example",
    urlPatterns = "/requests/log"
)
public class LoggingServlet extends HttpServlet {

  private static final Logger log = Logger.getLogger(LoggingServlet.class.getName());

  @Override
  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    log.info("An informational message.");
    log.warning("A warning message.");
    log.severe("An error message.");
    // ...
  }
}

Das Java-SDK für App Engine enthält im appengine-java-sdk/config/user/-Verzeichnis eine logging.properties-Vorlagendatei. Kopieren Sie die Datei zum Verwenden in Ihr WEB-INF/classes-Verzeichnis (oder an eine andere Stelle im WAR) und anschließend das Systemattribut java.util.logging.config.file in "WEB-INF/logging.properties" (oder in den von Ihnen ausgewählten Pfad, relativ zum Stammverzeichnis der Anwendung). Sie können die Systemattribute so in der Datei appengine-web.xml festlegen:

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0"> ... <system-properties> <property name="java.util.logging.config.file" value="WEB-INF/logging.properties" /> </system-properties> </appengine-web-app>

Das Servlet protokolliert Nachrichten auf der Logebene INFO mit log.info(). Die Standard-Logebene ist WARNING, mit der Nachrichten vom Typ INFO in der Ausgabe ausgeblendet werden. Zum Ändern der Logebene bearbeiten Sie die Datei logging.properties. Ein Beispiel speziell für das Festlegen von Logebenen sehen Sie in der Anwendung Guestbook Form.

Umgebung

Alle Systemattribute und Umgebungsvariablen betreffen ausschließlich Ihre Anwendung. Das Festlegen eines Systemattributs beeinflusst nur die Ansicht für dieses Attribut in Ihrer Anwendung und nicht die Ansicht in der JVM.

Systemattribute und Umgebungsvariablen der Anwendung können Sie im Bereitstellungsdeskriptor festlegen.

Bei App Engine werden mehrere Systemattribute festgelegt, die die Laufzeitumgebung identifizieren:

  • com.google.appengine.runtime.environment ist "Production" beim Ausführen auf App Engine und "Development" beim Ausführen auf dem Entwicklungsserver.

    Neben System.getProperty() können Sie auch über unsere typsichere API auf Systemattribute zugreifen. Beispiel:

    if (SystemProperty.environment.value() ==
        SystemProperty.Environment.Value.Production) {
        // The app is running on App Engine...
    }
    
  • com.google.appengine.runtime.version ist die Versions-ID der Laufzeitumgebung, z. B. "1.3.0". Sie erhalten die Version, indem Sie folgenden Befehl aufrufen: String version = SystemProperty.version.get();

  • com.google.appengine.application.id ist die ID der Anwendung. Sie erhalten die ID, indem Sie folgenden Befehl aufrufen: String ID = SystemProperty.applicationId.get();

  • com.google.appengine.application.version ist die Haupt- und Nebenversion des aktuell ausgeführten Anwendungsdienstes in der Form "X.Y". Die Hauptversionsnummer ("X") ist in der appengine-web.xml-Datei des Dienstes angegeben. Die Nebenversionsnummer ("Y") wird beim Hochladen der einzelnen Versionen der Anwendung in App Engine automatisch festgelegt. Sie erhalten die ID, indem Sie folgenden Befehl aufrufen: String ID = SystemProperty.applicationVersion.get();

    Auf dem Entwicklungs-Webserver ist die Hauptversion immer die Version des Standarddienstes, die Nebenversion ist immer "1".

App Engine legt auch die folgenden Systemattribute fest, wenn die JVM auf einem Anwendungsserver initialisiert wird:

  • file.separator
  • path.separator
  • line.separator
  • java.version
  • java.vendor
  • java.vendor.url
  • java.class.version
  • java.specification.version
  • java.specification.vendor
  • java.specification.name
  • java.vm.vendor
  • java.vm.name
  • java.vm.specification.version
  • java.vm.specification.vendor
  • java.vm.specification.name
  • user.dir

Instanz-IDs

Mit diesem Code können Sie die ID der Instanz abrufen, mit der eine Anfrage bearbeitet wird:

com.google.apphosting.api.ApiProxy.getCurrentEnvironment().getAttributes().get("com.google.appengine.instance.id")

In der Produktionsumgebung kann ein angemeldeter Administrator die ID in einer URL verwenden: https://INSTANCE_ID-dot-VERSION_ID-dot-SERVICE_ID-dot-PROJECT_ID.REGION_ID.r.appspot.com. Die Anfrage wird an diese bestimmte Instanz weitergeleitet. Wenn die Instanz die Anfrage nicht verarbeiten kann, wird sofort ein 503-Fehler zurückgegeben.

Anfrage-IDs

Beim Senden der Anfrage kann die eindeutige Anfrage-ID gespeichert werden. Sie kann später verwendet werden, um eine Anfrage und die Logs für diese Anfrage zu korrelieren.

Der folgende Code zeigt, wie die Anfrage-ID im Kontext einer Anfrage abgerufen wird:

com.google.apphosting.api.ApiProxy.getCurrentEnvironment().getAttributes().get("com.google.appengine.runtime.request_log_id")

HTTPS-Verbindungen erzwingen

Aus Sicherheitsgründen sollten alle Anwendungen von Clients eine Verbindung über https anfordern. Um den Browser anzuweisen, für eine bestimmte Seite oder für die gesamte Domain https statt http zu verwenden, legen Sie in Ihren Antworten den Header Strict-Transport-Security fest. Beispiel:

Strict-Transport-Security: max-age=31536000; includeSubDomains
Zum Festlegen dieses Headers für statische Inhalte, die von Ihrer Anwendung bereitgestellt werden, fügen Sie den Header den statischen Datei- und Verzeichnis-Handlern Ihrer Anwendung hinzu.

Die meisten Anwendungs-Frameworks und Webserver unterstützen die Festlegung dieses Headers für von Ihrem Code generierte Antworten. Informationen zum Header Strict-Transport-Security in Spring Boot finden Sie unter HTTP Strict Transport Security (HSTS).