So verwenden Sie App Engine-Aufgabenwarteschlange (Push-Aufgaben) in Flask-Anwendungen (Modul 7)

1. Übersicht

Die Codelabs der Reihe „Serverless Migration Station“ (selbstgesteuerte, praktische Anleitungen) und die zugehörigen Videos sollen serverlosen Google Cloud-Entwicklern helfen, ihre Anwendungen zu modernisieren. Dazu werden sie durch eine oder mehrere Migrationen geführt, bei denen es in erster Linie darum geht, von Legacy-Diensten wegzukommen. Dadurch werden Ihre Apps portierbarer und Sie erhalten mehr Optionen und Flexibilität. Sie können eine größere Auswahl an Cloud-Produkten einbinden und darauf zugreifen und einfacher auf neuere Sprachversionen upgraden. Die Reihe konzentriert sich zwar anfangs auf die ersten Cloud-Nutzer, vor allem auf App Engine-Entwickler (Standardumgebung), ist aber breit genug, um auch andere serverlose Plattformen wie Cloud Functions und Cloud Run oder andere Plattformen einzubeziehen, sofern zutreffend.

In diesem Codelab erfahren Sie, wie Sie App Engine-Aufgabenwarteschlangen-Push-Aufgaben in der Beispielanwendung aus dem Codelab zu Modul 1 verwenden. Der Blogpost und das Video zu Modul 7 ergänzen diese Anleitung und bieten einen kurzen Überblick über die Inhalte dieser Anleitung.

In diesem Modul fügen wir die Verwendung von Push-Aufgaben hinzu. In Modul 8 migrieren wir diese Verwendung zu Cloud Tasks und in Modul 9 zu Python 3 und Cloud Datastore. Nutzer, die Aufgabenwarteschlangen für Pull-Aufgaben verwenden, migrieren zu Cloud Pub/Sub und sollten stattdessen die Module 18–19 lesen.

Lerninhalte

  • App Engine Task Queue API/gebündelten Dienst verwenden
  • Push-Aufgaben einer einfachen Python 2-Flask-App mit App Engine NDB hinzufügen

Voraussetzungen

Umfrage

Wie werden Sie diese Anleitung verwenden?

Nur lesen Lesen und Übungen durchführen

Wie würden Sie Ihre Erfahrung mit Python bewerten?

Anfänger Mittelstufe Fortgeschrittene

Wie würden Sie Ihre Erfahrungen mit Google Cloud-Diensten bewerten?

Anfänger Mittelstufe Fortgeschritten

2. Hintergrund

Die App Engine Task Queue unterstützt sowohl Push- als auch Pull-Aufgaben. Um die Portabilität von Anwendungen zu verbessern, empfiehlt das Google Cloud-Team, von gebündelten Legacy-Diensten wie Task Queue zu anderen eigenständigen Cloud- oder Drittanbieterdiensten zu migrieren.

Die Migration von Pull-Aufgaben wird in den Migrationsmodulen 18–19 behandelt, während sich die Module 7–9 auf die Migration von Push-Aufgaben konzentrieren. Wenn Sie Push-Aufgaben aus der App Engine-Aufgabenwarteschlange migrieren möchten, fügen Sie die Verwendung der Aufgabenwarteschlange der vorhandenen Flask- und App Engine NDB-App hinzu, die aus dem Codelab zu Modul 1 stammt. In dieser App wird bei jedem neuen Seitenaufruf ein neuer Besuch registriert und die letzten Besuche des Nutzers werden angezeigt. Da ältere Besuche nie wieder angezeigt werden und Speicherplatz im Datastore belegen, erstellen wir eine Push-Aufgabe, um die ältesten Besuche automatisch zu löschen. In Modul 8 migrieren wir diese App von Task Queue zu Cloud Tasks.

Diese Anleitung umfasst die folgenden Schritte:

  1. Einrichtung/Vorbereitung
  2. Konfiguration aktualisieren
  3. Anwendungscode ändern

3. Einrichtung/Vorbereitung

In diesem Abschnitt wird Folgendes erläutert:

  1. Cloud-Projekt einrichten
  2. Beispiel-App für die Baseline abrufen
  3. Ausgangsanwendung (neu) bereitstellen und validieren

Mit diesen Schritten stellen Sie sicher, dass Sie mit funktionierendem Code beginnen.

1. Projekt einrichten

Wenn Sie das Codelab zu Modul 1 abgeschlossen haben, empfehlen wir, dasselbe Projekt (und denselben Code) wiederzuverwenden. Alternativ können Sie ein neues Projekt erstellen oder ein anderes vorhandenes Projekt wiederverwenden. Prüfen Sie, ob das Projekt ein aktives Rechnungskonto hat und App Engine aktiviert ist.

2. Beispiel-App für die Baseline abrufen

Eine der Voraussetzungen für dieses Codelab ist eine funktionierende App Engine-App aus Modul 1. Führen Sie das Codelab zu Modul 1 aus (empfohlen) oder kopieren Sie die App aus Modul 1 aus dem Repository. Unabhängig davon, ob Sie Ihren oder unseren Code verwenden, ist der Code aus Modul 1 der Ausgangspunkt. In diesem Codelab werden Sie durch jeden Schritt geführt. Am Ende erhalten Sie Code, der dem im Repo-Ordner „FINISH“ von Modul 7 ähnelt.

Unabhängig davon, welche App aus Modul 1 Sie verwenden, sollte der Ordner so aussehen wie unten, möglicherweise auch mit einem lib-Ordner:

$ ls
README.md               main.py                 templates
app.yaml                requirements.txt

3. Referenz-App (erneut) bereitstellen

Führen Sie die folgenden Schritte aus, um die App aus Modul 1 (neu) bereitzustellen:

  1. Löschen Sie den Ordner lib, falls er vorhanden ist, und führen Sie pip install -t lib -r requirements.txt aus, um lib neu zu füllen. Wenn Sie sowohl Python 2 als auch Python 3 installiert haben, müssen Sie möglicherweise stattdessen den Befehl pip2 verwenden.
  2. Achten Sie darauf, dass Sie das gcloud-Befehlszeilentool installiert und initialisiert haben und sich mit der Verwendung vertraut gemacht haben.
  3. Legen Sie Ihr Cloud-Projekt mit gcloud config set project PROJECT_ID fest, wenn Sie Ihre PROJECT_ID nicht bei jedem ausgeführten gcloud-Befehl eingeben möchten.
  4. Beispiel-App mit gcloud app deploy bereitstellen
  5. Prüfen Sie, ob die App aus Modul 1 wie erwartet ausgeführt wird und die letzten Besuche ohne Probleme angezeigt werden (siehe unten).

a7a9d2b80d706a2b.png

4. Konfiguration aktualisieren

An den Standardkonfigurationsdateien für App Engine (app.yaml, requirements.txt, appengine_config.py) sind keine Änderungen erforderlich.

5. Anwendungsdateien ändern

Die primäre Anwendungsdatei ist main.py. Alle Aktualisierungen in diesem Abschnitt beziehen sich auf diese Datei. Außerdem gibt es eine kleinere Aktualisierung der Webvorlage templates/index.html. Das sind die Änderungen, die in diesem Abschnitt vorgenommen werden müssen:

  1. Importe aktualisieren
  2. Push-Aufgabe hinzufügen
  3. Aufgaben-Handler hinzufügen
  4. Webvorlage aktualisieren

1. Importe aktualisieren

Durch den Import von google.appengine.api.taskqueue wird die Task Queue-Funktionalität eingeführt. Außerdem sind einige Pakete der Python-Standardbibliothek erforderlich:

  • Da wir eine Aufgabe zum Löschen der ältesten Besuche hinzufügen, muss die App Zeitstempel verarbeiten, d. h. time und datetime verwenden.
  • Damit wir nützliche Informationen zur Ausführung von Aufgaben protokollieren können, benötigen wir logging.

Nachdem Sie alle diese Importe hinzugefügt haben, sieht Ihr Code vor und nach diesen Änderungen so aus:

VORHER:

from flask import Flask, render_template, request
from google.appengine.ext import ndb

DANACH:

from datetime import datetime
import logging
import time
from flask import Flask, render_template, request
from google.appengine.api import taskqueue
from google.appengine.ext import ndb

2. Push-Aufgabe hinzufügen (Daten für Aufgabe zusammenstellen, neue Aufgabe in die Warteschlange stellen)

In der Dokumentation zu Push-Warteschlangen heißt es: „Um eine Aufgabe zu bearbeiten, müssen Sie sie zu einer Push-Warteschlange hinzufügen. App Engine stellt eine Standard-Push-Warteschlange mit dem Namen default zur Verfügung, die fertig konfiguriert und für die Verwendung mit Standardeinstellungen bereit ist. Sie können grundsätzlich einfach alle Aufgaben in die Standardwarteschlange aufnehmen und müssen dann keine anderen Warteschlangen erstellen und konfigurieren.“ In diesem Codelab wird der Einfachheit halber die default-Warteschlange verwendet. Weitere Informationen zum Definieren eigener Push-Warteschlangen mit denselben oder unterschiedlichen Merkmalen finden Sie in der Dokumentation zum Erstellen von Push-Warteschlangen.

Das primäre Ziel dieses Codelabs ist es, eine Aufgabe (für die default-Push-Warteschlange) hinzuzufügen, die alte Besuche aus Datastore löscht, die nicht mehr angezeigt werden. In der Baseline-App wird jeder Besuch (GET-Anfrage an /) registriert, indem eine neue Visit-Entität erstellt wird. Anschließend werden die letzten Besuche abgerufen und angezeigt. Die ältesten Besuche werden nie wieder angezeigt oder verwendet. Der Push-Vorgang löscht daher alle Besuche, die älter als der älteste angezeigte Besuch sind. Dazu muss sich das Verhalten der App etwas ändern:

  1. Wenn Sie die letzten Besuche abfragen, sollten Sie die App so ändern, dass sie den Zeitstempel des letzten Visit speichert, der älteste, der angezeigt wird. Alle Besuche, die älter als dieser sind, können gefahrlos gelöscht werden.
  2. Erstellen Sie eine Push-Aufgabe mit diesem Zeitstempel als Nutzlast und leiten Sie sie an den Aufgaben-Handler weiter, der über einen HTTP-POST an /trim erreichbar ist. Verwenden Sie dazu Standard-Python-Dienstprogramme, um den Datastore-Zeitstempel zu konvertieren und als Gleitkommazahl an die Aufgabe zu senden. Protokollieren Sie ihn aber auch als String und geben Sie diesen String als Sentinel-Wert zurück, der dem Nutzer angezeigt werden soll.

Das alles findet in fetch_visits() statt. So sieht es vor und nach den Aktualisierungen aus:

VORHER:

def fetch_visits(limit):
    return (v.to_dict() for v in Visit.query().order(
            -Visit.timestamp).fetch(limit))

DANACH:

def fetch_visits(limit):
    'get most recent visits and add task to delete older visits'
    data = Visit.query().order(-Visit.timestamp).fetch(limit)
    oldest = time.mktime(data[-1].timestamp.timetuple())
    oldest_str = time.ctime(oldest)
    logging.info('Delete entities older than %s' % oldest_str)
    taskqueue.add(url='/trim', params={'oldest': oldest})
    return (v.to_dict() for v in data), oldest_str

3. Aufgaben-Handler hinzufügen (Code, der beim Ausführen der Aufgabe aufgerufen wird)

Das Löschen alter Besuche hätte in fetch_visits() problemlos erfolgen können. Diese Funktion hat jedoch nicht viel mit dem Endnutzer zu tun. Es handelt sich um eine Hilfsfunktion, die sich gut für die asynchrone Verarbeitung außerhalb von Standard-App-Anfragen eignet. Endnutzer profitieren von schnelleren Abfragen, da weniger Informationen in Datastore vorhanden sind. Erstellen Sie eine neue Funktion trim(), die über eine Task Queue-Anfrage POST an /trim aufgerufen wird und Folgendes ausführt:

  1. Extrahiert die Nutzlast mit dem Zeitstempel des „ältesten Besuchs“
  2. Führt eine Datastore-Abfrage aus, um alle Entitäten zu finden, die älter als dieser Zeitstempel sind.
  3. Entscheidet sich für eine schnellere „ausschließlich schlüsselbasierte“ Abfrage, da keine tatsächlichen Nutzerdaten erforderlich sind.
  4. Protokolliert die Anzahl der zu löschenden Einheiten (einschließlich null).
  5. Ruft ndb.delete_multi() auf, um alle Entitäten zu löschen (wird übersprungen, falls nicht).
  6. Gibt einen leeren String (zusammen mit einem impliziten HTTP 200-Rückgabecode) zurück.

Das alles sehen Sie unten in trim(). Fügen Sie es main.py direkt nach fetch_visits() hinzu:

@app.route('/trim', methods=['POST'])
def trim():
    '(push) task queue handler to delete oldest visits'
    oldest = request.form.get('oldest', type=float)
    keys = Visit.query(
            Visit.timestamp < datetime.fromtimestamp(oldest)
    ).fetch(keys_only=True)
    nkeys = len(keys)
    if nkeys:
        logging.info('Deleting %d entities: %s' % (
                nkeys, ', '.join(str(k.id()) for k in keys)))
        ndb.delete_multi(keys)
    else:
        logging.info('No entities older than: %s' % time.ctime(oldest))
    return ''   # need to return SOME string w/200

4. Webvorlage aktualisieren

Aktualisieren Sie die Webvorlage templates/index.html mit dieser Jinja2-Bedingung, um den ältesten Zeitstempel anzuzeigen, falls diese Variable vorhanden ist:

{% if oldest is defined %}
    <b>Deleting visits older than:</b> {{ oldest }}</p>
{% endif %}

Fügen Sie dieses Snippet nach der Liste der angezeigten Besuche, aber vor dem schließenden body-Tag ein, damit Ihre Vorlage so aussieht:

<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
<body>

<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
    <li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>

{% if oldest is defined %}
    <b>Deleting visits older than:</b> {{ oldest }}</p>
{% endif %}
</body>
</html>

6. Zusammenfassung/Bereinigung

In diesem Abschnitt wird das Codelab abgeschlossen, indem die App bereitgestellt und geprüft wird, ob sie wie vorgesehen funktioniert und ob die Ausgabe korrekt ist. Führen Sie nach der App-Validierung alle erforderlichen Bereinigungen durch und überlegen Sie sich die nächsten Schritte.

Anwendung bereitstellen und überprüfen

Stellen Sie die App mit gcloud app deploy bereit. Die Ausgabe sollte mit der App aus Modul 1 identisch sein, mit Ausnahme einer neuen Zeile unten, in der angezeigt wird, welche Besuche gelöscht werden:

4aa8a2cb5f527079.png

Herzlichen Glückwunsch zum Abschluss des Codelabs. Ihr Code sollte jetzt mit dem Code im Repo-Ordner für Modul 7 übereinstimmen. Sie können jetzt zu Cloud Tasks in Modul 8 migrieren.

Bereinigen

Allgemein

Wenn Sie die App vorerst nicht mehr benötigen, empfehlen wir Ihnen, sie zu deaktivieren, um Abrechnungen zu vermeiden. Wenn Sie jedoch weitere Tests durchführen möchten, bietet die App Engine-Plattform ein kostenloses Kontingent. Solange Sie diese Nutzungsebene nicht überschreiten, werden Ihnen keine Gebühren berechnet. Das gilt für die Rechenleistung. Es können aber auch Gebühren für relevante App Engine-Dienste anfallen. Weitere Informationen finden Sie auf der Preisseite. Wenn bei dieser Migration andere Cloud-Dienste beteiligt sind, werden diese separat abgerechnet. Sehen Sie sich in beiden Fällen gegebenenfalls den Abschnitt „Spezifisch für dieses Codelab“ unten an.

Die Bereitstellung auf einer serverlosen Google Cloud-Compute-Plattform wie App Engine verursacht geringe Build- und Speicherkosten. Cloud Build und Cloud Storage haben jeweils ein eigenes kostenloses Kontingent. Das Speichern dieses Bildes verbraucht einen Teil dieses Kontingents. Möglicherweise leben Sie jedoch in einer Region, in der es kein solches kostenloses Kontingent gibt. Achten Sie daher auf Ihre Speichernutzung, um potenzielle Kosten zu minimieren. Folgende Cloud Storage-„Ordner“ sollten Sie sich ansehen:

  • console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/images
  • console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com
  • Die oben genannten Speicherlinks hängen von Ihrem PROJECT_ID und *LOC*ab, z. B. „us“, wenn Ihre App in den USA gehostet wird.

Wenn Sie diese Anwendung oder andere zugehörige Migrations-Codelabs nicht weiter verwenden und alles vollständig löschen möchten, beenden Sie Ihr Projekt.

Spezifisch für dieses Codelab

Die unten aufgeführten Dienste sind nur für dieses Codelab verfügbar. Weitere Informationen finden Sie in der Dokumentation der einzelnen Produkte:

Nächste Schritte

Bei dieser „Migration“ haben Sie der Beispielanwendung aus Modul 1 die Verwendung von Push-Warteschlangen für Task Queue hinzugefügt und so die Unterstützung für das Erfassen von Besucherdaten ermöglicht. Das Ergebnis ist die Beispielanwendung aus Modul 7. In der nächsten Migration erfahren Sie, wie Sie ein Upgrade von App Engine-Push-Tasks auf Cloud Tasks durchführen können. Seit Herbst 2021 müssen Nutzer bei einem Upgrade auf Python 3 nicht mehr zu Cloud Tasks migrieren. Weitere Informationen finden Sie im nächsten Abschnitt.

Wenn Sie zu Cloud Tasks wechseln möchten, ist das Codelab für Modul 8 der nächste Schritt. Darüber hinaus sind weitere Migrationen zu berücksichtigen, z. B. Cloud Datastore, Cloud Memorystore, Cloud Storage oder Cloud Pub/Sub (Pull-Warteschlangen). Es gibt auch produktübergreifende Migrationen zu Cloud Run und Cloud Functions. Alle Serverless Migration Station-Inhalte (Codelabs, Videos, Quellcode [sofern verfügbar]) sind im zugehörigen Open-Source-Repository verfügbar.

7. Migration zu Python 3

Im Herbst 2021 hat das App Engine-Team die Unterstützung vieler gebündelter Dienste auf Laufzeiten der 2. Generation ausgeweitet (ursprünglich nur in Laufzeiten der 1. Generation verfügbar). Das bedeutet, dass Sie bei der Portierung Ihrer App zu Python 3 nicht mehr von gebündelten Diensten wie App Engine Task Queue zu eigenständigen Cloud- oder Drittanbieter-Alternativen wie Cloud Tasks migrieren müssen. Mit anderen Worten: Sie können Task Queue weiterhin in Python 3-App Engine-Anwendungen verwenden, sofern Sie den Code so anpassen, dass über Laufzeiten der nächsten Generation auf gebündelte Dienste zugegriffen wird.

Weitere Informationen zur Migration der Verwendung gebündelter Dienste zu Python 3 finden Sie im Codelab zu Modul 17 und im entsprechenden Video. Dieses Thema fällt nicht in den Rahmen von Modul 7. Unten finden Sie jedoch Python 3-Versionen der Apps aus Modul 1 und Modul 7, die zu Python 3 portiert wurden und weiterhin App Engine NDB und Task Queue verwenden.

8. Zusätzliche Ressourcen

Unten finden Sie weitere Ressourcen für Entwickler, die sich näher mit diesem oder einem ähnlichen Migrationsmodul sowie mit zugehörigen Produkten befassen möchten. Dazu gehören Orte, an denen Sie Feedback zu diesen Inhalten geben können, Links zum Code und verschiedene Dokumentationen, die für Sie nützlich sein könnten.

Probleme mit Codelabs/Feedback

Wenn Sie Probleme mit diesem Codelab feststellen, suchen Sie bitte zuerst nach Ihrem Problem, bevor Sie es melden. Links zum Suchen und Erstellen neuer Probleme:

Migrationsressourcen

Links zu den Repository-Ordnern für Modul 2 (START) und Modul 7 (FINISH) finden Sie in der Tabelle unten.

Codelab

Python 2

Python 3

Modul 1

code

Code (nicht in diesem Tutorial enthalten)

Modul 7 (dieses Codelab)

code

Code (nicht in diesem Tutorial enthalten)

Onlineressourcen

Unten finden Sie Online-Ressourcen, die für diese Anleitung relevant sein könnten:

App Engine-Aufgabenwarteschlange

App Engine-Plattform

Andere Cloud-Informationen

Videos

Lizenz

Dieser Text ist mit einer Creative Commons Attribution 2.0 Generic License lizenziert.