Anfrageverarbeitung

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 Web-Framework verwenden, das für Ihre Programmiersprache verfügbar ist.

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. Daher werden aufeinanderfolgende Anfragen von einem Nutzer nicht zwangsläufig an dieselbe Instanz gesendet. Eine Instanz kann mehrere Anfragen gleichzeitig verarbeiten. Die Anzahl der Instanzen wird automatisch angepasst, wenn sich der Traffic ändert. Es besteht auch die Möglichkeit, die Anzahl gleichzeitiger Anfragen, die eine Instanz verarbeiten kann, individuell festzulegen. Dazu geben Sie in der Datei "app.yaml" das Element max_concurrent_requests an.

Wenn App Engine eine Webanfrage für Ihre Anwendung empfängt, wird gemäß Beschreibung in der Konfigurationsdatei app.yaml der Anwendung das Handler-Skript aufgerufen, das der URL entspricht. Die Python 2.7-Laufzeit unterstützt den WSGI-Standard und den CGI-Standard, um eine Abwärtskompatibilität zu erreichen. WSGI wird bevorzugt und ist für einige Funktionen von Python 2.7 Voraussetzung. Die Konfiguration der Skript-Handler Ihrer Anwendung bestimmt, ob eine Anfrage mit WSGI oder CGI verarbeitet wird.

Das folgende Python-Skript antwortet auf eine Anfrage mit einem HTTP-Header und der Nachricht Hello, World!.

import webapp2

class MainPage(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.write('Hello, World!')

app = webapp2.WSGIApplication([
    ('/', MainPage),
], debug=True)

Wenn Sie parallel mehrere Anfragen an jeden Webserver senden möchten, markieren Sie die Anwendung als threadsicher. Dazu fügen Sie der Datei app.yaml das Element threadsafe: true hinzu. Gleichzeitige Anfragen sind nicht verfügbar, wenn von einem der Skript-Handler CGI verwendet wird.

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. Als Antwort auf eine Anfrage gesendete Daten werden auf das Limit Ausgehende Bandbreite (kostenpflichtig) angerechnet.

Sowohl HTTP- als auch (sichere) HTTPS-Anfragen werden auf die Limits für Anfragen, Eingehende Bandbreite (kostenpflichtig) und Ausgehende Bandbreite (kostenpflichtig) angerechnet. In der GCP Console werden auf der Seite "Kontingente" zu Informationszwecken außerdem Sichere Anfragen, Sichere eingehende Bandbreite und Sichere ausgehende Bandbreite als separate Werte angezeigt. In diese Werte gehen 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
Anfragedauer 60 Sekunden
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 GB ist kostenlos;
0,026 $ pro GB und 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 Wert ü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.

Antworten auf Anfragen

In App Engine wird das Handler-Skript mit Request aufgerufen und auf dessen Antwort gewartet. Alle Daten, die in den Standardausgabestream geschrieben werden, werden als HTTP-Antwort gesendet.

Für die generierte Antwort gelten Beschränkungen. Unter Umständen wird die Antwort vor der Rückgabe an den Client geändert.

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

Wenn der Client mit der ursprünglichen Anfrage HTTP-Header sendet, in denen angegeben ist, dass der Client mit gzip komprimierte Inhalte annehmen kann, werden die Handler-Antwortdaten von App Engine automatisch komprimiert und die entsprechenden Antwortheader angefügt. Dabei werden die Anfrageheader Accept-Encoding und User-Agent verwendet, um festzustellen, ob der Client komprimierte Antworten zuverlässig empfangen kann.

Bei benutzerdefinierten Clients kann mit dem Wert gzip in den beiden Headern Accept-Encoding und User-Agent angegeben werden, dass komprimierte Antworten empfangen werden können. Auch der Content-Type der Antwort wird verwendet, um zu bestimmen, ob eine Komprimierung angebracht ist. Im Allgemeinen werden textbasierte Inhaltstypen komprimiert, binäre Inhaltstypen hingegen nicht.

Wenn Antworten von App Engine automatisch komprimiert werden, wird der Antwort der Header Content-Encoding hinzugefügt.

Zeitlimit für Anfragen setzen

Der Zeitraum, in dem ein Anfrage-Handler eine Antwort auf eine Anfrage erzeugen und zurücksenden muss, ist normalerweise auf 60 Sekunden begrenzt. Wenn diese Zeit abgelaufen ist, wird die Verbindung des Anfrage-Handlers unterbrochen. Die Python-Laufzeitumgebung unterbricht die Verbindung des Anfrage-Handlers mit einem DeadlineExceededError aus dem Paket google.appengine.runtime. Falls der Anfrage-Handler diese Ausnahme nicht abfängt, gibt die Laufzeitumgebung, wie es bei allen nicht abgefangenen Ausnahmen der Fall ist, den HTTP-Serverfehler 500 an den Client zurück.

Der Anfrage-Handler kann diesen Fehler abfangen, um die Antwort anzupassen. Die Laufzeitumgebung stellt dem Anfrage-Handler noch einen kurzen Zeitraum (unter einer Sekunde) zur Verfügung, nachdem die Ausnahme ausgelöst wurde, in dem eine angepasste Antwort vorbereitet werden kann.

class TimerHandler(webapp2.RequestHandler):
    def get(self):
        from google.appengine.runtime import DeadlineExceededError

        try:
            time.sleep(70)
            self.response.write('Completed.')
        except DeadlineExceededError:
            self.response.clear()
            self.response.set_status(500)
            self.response.out.write(
                'The request did not complete in time.')

Falls der Handler innerhalb der zweiten Frist keine Antwort zurückgibt oder keine Ausnahme auslöst, wird er beendet und es wird eine Standardfehlerantwort zurückgegeben.

Die Antwort auf eine Anfrage kann bis zu 60 Sekunden dauern. App Engine ist jedoch auf Anwendungen mit kurzlebigen Anfragen optimiert, die in der Regel nur 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.

Weitere Informationen zu häufigen Ursachen für den Fehler DeadlineExceededError und Empfehlungen zur Abhilfe finden Sie unter DeadlineExceededError.

Logging

Der App Engine-Webserver erfasst alle Daten, die vom Handler-Skript in den Standardausgabestream für die Antwort auf die Webanfrage geschrieben werden. Er erfasst auch alles, was das Handler-Skript in den Standardfehlerstream schreibt, und speichert diese Daten als Log-Daten. Jeder Anfrage wird eine request_id zugewiesen, eine global eindeutige Kennung, die auf der Startzeit der Anfrage basiert. Die Logdaten für die Anwendung können Sie in der GCP Console über Stackdriver Logging einsehen.

Die Python-Laufzeitumgebung von App Engine enthält spezielle Unterstützung für das Logging-Modul aus der Python-Standardbibliothek, um Logging-Konzepte wie Logging-Ebenen ("debug", "info", "warning", "error", "critical") zu verstehen.

import logging

import webapp2

class MainPage(webapp2.RequestHandler):
    def get(self):
        logging.debug('This is a debug message')
        logging.info('This is an info message')
        logging.warning('This is a warning message')
        logging.error('This is an error message')
        logging.critical('This is a critical message')

        try:
            raise ValueError('This is a sample value error.')
        except ValueError:
            logging.exception('A example exception log.')

        self.response.out.write('Logging example.')

app = webapp2.WSGIApplication([
    ('/', MainPage)
], debug=True)

Umgebung

Die Ausführungsumgebung legt automatisch mehrere Umgebungsvariablen fest. Sie können weitere in der Datei app.yaml festlegen. Einige der automatisch festgelegten Variablen gelten speziell für App Engine und andere sind Bestandteil des WSGI- oder CGI-Standards. Python-Code kann über das Wörterbuch os.environ auf diese Variablen zugreifen.

Die folgenden Umgebungsvariablen gelten speziell für App Engine:

  • CURRENT_VERSION_ID: Die Haupt- und Nebenversion der aktuell ausgeführten Anwendung im Format "X.Y". Die Hauptversionsnummer ("X") ist in der Datei app.yaml der Anwendung angegeben. Die Nebenversionsnummer ("Y") wird beim Hochladen der einzelnen Versionen der Anwendung in App Engine automatisch festgelegt. Auf dem Entwicklungs-Webserver ist die Nebenversion immer "1".

  • AUTH_DOMAIN: Die Domain, die zum Authentifizieren von Nutzern mit der Users API verwendet wird. Auf appspot.com gehostete Anwendungen haben eine AUTH_DOMAIN von gmail.com und akzeptieren jedes Google-Konto. Die AUTH_DOMAIN von Anwendungen, die auf einer benutzerdefinierten Domain gehostet werden, entspricht derjenigen der benutzerdefinierten Domain.

  • INSTANCE_ID: Enthält die Instanz-ID der Front-End-Instanz, die eine Anfrage verarbeitet. Die ID ist ein Hexadezimalstring (z. B. 00c61b117c7f7fd0ce9e1325a04b8f0df30deaaf). Ein angemeldeter Administrator kann die ID in einer URL verwenden: http://[INSTANCE_ID].myApp.appspot.com/. Die Anfrage wird an diese bestimmte Front-End-Instanz weitergeleitet. Wenn die Instanz die Anfrage nicht verarbeiten kann, wird sofort der Fehler 503 zurückgegeben.

Die folgenden Umgebungsvariablen sind Bestandteil der WSGI- und CGI-Standards, die ein besonderes Verhalten in App Engine zeigen:

  • SERVER_SOFTWARE: Im Entwicklungs-Webserver lautet dieser Wert "Development/X.Y", wobei "X.Y" die Version der Laufzeit ist. In App Engine lautet dieser Wert "Google App Engine/X.Y.Z".

Zusätzliche Umgebungsvariablen werden nach dem WSGI- oder CGI-Standard festgelegt. Weitere Informationen zu diesen Variablen finden Sie im WSGI-Standard bzw. im CGI-Standard.

Sie können Umgebungsvariablen auch in der Datei app.yaml festlegen:

env_variables:
  DJANGO_SETTINGS_MODULE: 'myapp.settings'

Der folgende webapp2-Anfrage-Handler zeigt jede Umgebungsvariable an, die für die Anwendung im Browser sichtbar ist:

class PrintEnvironmentHandler(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        for key, value in os.environ.iteritems():
            self.response.out.write(
                "{} = {}\n".format(key, value))

Anfrage-IDs

Zum Zeitpunkt der Anfrage können Sie die für diese Anfrage eindeutige Anfrage-ID speichern. Sie können die Anfrage-ID später verwenden, um die Logs für diese Anfrage in Stackdriver Logging abzurufen.

Das folgende Codebeispiel zeigt, wie die Anfrage-ID im Kontext einer Anfrage abgerufen wird:

class RequestIdHandler(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        request_id = os.environ.get('REQUEST_LOG_ID')
        self.response.write(
            'REQUEST_LOG_ID={}'.format(request_id))

Anwendungs-Caching

Ähnlich wie eine eigenständige Python-Anwendung, die ein Modul auch dann nur einmal lädt, wenn es von mehreren Dateien importiert wird, speichert die Python-Laufzeitumgebung importierte Module zwischen Anfragen auf einem einzelnen Webserver im Cache. Da es sich bei WSGI-Handlern um Module handelt, werden sie zwischen Anfragen im Cache gespeichert. CGI-Handler-Skripts werden nur im Cache gespeichert, wenn sie die Routine main() bereitstellen. Andernfalls wird das CGI-Handler-Skript für jede Anfrage geladen.

Durch das Anwendungs-Caching werden Antwortzeiten erheblich verkürzt. Wir empfehlen die Verwendung der Routine "main()" für alle CGI-Handler-Skripts gemäß der nachfolgenden Beschreibung.

Importe werden im Cache gespeichert

Zur Steigerung der Effizienz bewahrt der Webserver importierte Module im Speicher auf und lädt bzw. evaluiert sie nicht noch einmal, wenn später Anfragen an dieselbe Anwendung auf demselben Server erfolgen. Die meisten Module initialisieren keine globalen Daten und haben auch keine anderen Nebeneffekte, wenn sie importiert werden. Daher ändert sich das Verhalten der Anwendung nicht, wenn diese im Cache gespeichert werden.

Wenn Ihre Anwendung ein Modul importiert, das für jede Anfrage evaluiert werden muss, muss die Anwendung dieses Caching-Verhalten berücksichtigen.

CGI-Handler im Cache speichern

Sie können App Engine anweisen, zusätzlich zu den importierten Modulen das CGI-Handler-Skript selbst im Cache zu speichern. Wenn das Handler-Skript eine Funktion namens main() definiert, werden das Skript und seine globale Umgebung wie ein importiertes Modul im Cache gespeichert. Durch die erste Anfrage an das Skript auf einem gegebenen Webserver wird das Skript normal evaluiert. Bei nachfolgenden Anfragen ruft App Engine die Funktion main() in der im Cache gespeicherten Umgebung auf.

Wenn das Handler-Skript im Cache gespeichert werden soll, muss App Engine in der Lage sein, main() ohne Argumente aufzurufen. Wenn das Handler-Skript die Funktion main() nicht definiert oder die Funktion main() Argumente benötigt (die keine Standardwerte haben), lädt App Engine das gesamte Skript für jede Anfrage und wertet es aus.

Das Speichern des geparsten Python-Codes spart Zeit und es können schneller Antworten zurückgegeben werden. Das Speichern der globalen Umgebung im Cache bietet aber noch weitere potenzielle Verwendungsmöglichkeiten:

  • Kompilierte reguläre Ausdrücke. Alle regulären Ausdrücke werden geparst und in kompilierter Form gespeichert. Sie können kompilierte reguläre Ausdrücke in globalen Variablen speichern und die kompilierten Objekte mithilfe von Anwendungs-Caching zwischen Anfragen wiederholt verwenden.

  • GqlQuery-Objekte: Der GQL-Abfragestring wird zum Zeitpunkt der Erstellung des GqlQuery-Objekts geparst. Die wiederholte Verwendung eines GqlQuery-Objekts mit Parameterbindung und der Methode bind () ist schneller, als das Objekt jedes Mal neu zu konstruieren. Sie können ein GqlQuery-Objekt mit Parameterbindung für die Werte in einer globalen Variablen speichern und es anschließend durch Binden neuer Parameterwerte für jede Anfrage wiederverwenden.

  • Konfiguration und Datendateien: Falls Ihre Anwendung Konfigurationsdaten aus einer Datei lädt und parst, kann sie die geparsten Daten im Speicher behalten, damit die Datei nicht bei jeder Anfrage neu geladen werden muss.

Das Handler-Skript sollte beim Importieren die Funktion main() aufrufen. App Engine erwartet, dass beim Importieren des Skripts die Funktion main() aufgerufen wird. Deshalb ruft App Engine die Funktion beim ersten Laden des Anfrage-Handlers auf einem Server nicht auf.

Das Anwendungs-Caching mit main() bietet eine deutliche Verbesserung der Reaktionszeit Ihres CGI-Handlers. Wir empfehlen es für alle Anwendungen, die CGI verwenden.

Hat Ihnen diese Seite weitergeholfen? Teilen Sie uns Ihr Feedback mit:

Feedback geben zu...

App Engine-Standardumgebung für Python 2