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

1. Übersicht

Die Codelabs-Reihe zur Serverless Migration Station (zum Selbststudium, praxisorientierte Anleitungen) und ähnliche Videos sollen Entwickler von Google Cloud Serverless bei der Modernisierung ihrer Anwendungen unterstützen, indem sie eine oder mehrere Migrationen durchgehen, in erster Linie von Legacy-Diensten. Dadurch werden Ihre Anwendungen portabler und bieten mehr Optionen und Flexibilität, sodass Sie eine breitere Palette von Cloud-Produkten einbinden und darauf zugreifen sowie einfacher auf neuere Sprachversionen upgraden können. Der Schwerpunkt dieser Reihe liegt anfangs auf die ersten Cloud-Nutzer, in erster Linie auf Entwicklern von App Engine (Standardumgebung). Sie ist aber umfassend genug, um auch andere serverlose Plattformen wie Cloud Functions und Cloud Run oder gegebenenfalls andere Plattformen einzubeziehen.

In diesem Codelab erfahren Sie, wie Sie Push-Aufgaben für die App Engine-Aufgabenwarteschlange in der Beispiel-App aus dem Codelab für Modul 1 verwenden. Der Blogpost und das Video für Modul 7 ergänzen diese Anleitung und geben einen kurzen Überblick über die Inhalte der Anleitung.

In diesem Modul fügen wir die Verwendung von Push-Aufgaben hinzu. Anschließend migrieren wir diese Nutzung zu Cloud Tasks in Modul 8 und später zu Python 3 und zu Cloud Datastore in Modul 9. Diejenigen, die Aufgabenwarteschlangen für Pull-Aufgaben verwenden, migrieren zu Cloud Pub/Sub und sollten stattdessen auf die Module 18 bis 19 verweisen.

Sie werden lernen,

  • Verwenden Sie die App Engine Task Queue API bzw. den gebündelten Dienst.
  • Einfache App Engine NDB-Anwendung für Python 2 Flask Push-Aufgaben nutzen

Voraussetzungen

Umfrage

Wie möchten Sie diese Anleitung nutzen?

<ph type="x-smartling-placeholder"></ph> Nur bis zum Ende lesen Lies sie dir durch und absolviere die Übungen

Wie würden Sie Ihre Erfahrung mit Python bewerten?

<ph type="x-smartling-placeholder"></ph> Neuling Mittel Kompetent

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

<ph type="x-smartling-placeholder"></ph> Neuling Mittel Kompetent

2. Hintergrund

Die App Engine-Aufgabenwarteschlange unterstützt Push- und Pull-Aufgaben. Das Google Cloud-Team empfiehlt, von gebündelten Legacy-Diensten wie Task Queue zu anderen eigenständigen Cloud-Diensten oder entsprechenden Drittanbietern zu migrieren, um die Übertragbarkeit von Anwendungen zu verbessern.

Die Migration von Pull-Aufgaben wird in den Migrationsmodulen 18–19 behandelt, während sich die Module 7 bis 9 auf die Migration von Push-Aufgaben konzentrieren. Um von Push-Aufgaben der App Engine-Aufgabenwarteschlange zu migrieren, fügen Sie deren Nutzung der vorhandenen Flask- und App Engine NDB-Anwendung hinzu, die sich aus dem Codelab für Modul 1 ergibt. In dieser App wird durch einen neuen Seitenaufruf ein neuer Besuch registriert und dem Nutzer die letzten Besuche angezeigt. Da ältere Besuche nicht mehr angezeigt werden und Speicherplatz in Datastore belegen, erstellen wir eine Push-Aufgabe, mit der die ältesten Besuche automatisch gelöscht werden. Im Vorfeld von Modul 8 migrieren wir diese Anwendung von der Aufgabenwarteschlange zu Cloud Tasks.

Diese Anleitung umfasst die folgenden Schritte:

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

3. Einrichtung/Vorarbeit

In diesem Abschnitt wird Folgendes erläutert:

  1. Cloud-Projekt einrichten
  2. Baseline-Beispiel-App abrufen
  3. Referenz-App noch einmal bereitstellen und validieren

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

1. Projekt einrichten

Wenn Sie das Codelab für Modul 1 abgeschlossen haben, empfehlen wir Ihnen, dasselbe Projekt und denselben Code wiederzuverwenden. Alternativ können Sie ein ganz neues Projekt erstellen oder ein anderes vorhandenes Projekt wiederverwenden. Achten Sie darauf, dass das Projekt ein aktives Rechnungskonto hat und App Engine aktiviert ist.

2. Baseline-Beispiel-App abrufen

Eine der Voraussetzungen für dieses Codelab ist eine funktionierende App Engine-App für Modul 1. Schließen Sie das Codelab für Modul 1 ab (empfohlen) oder kopieren Sie die Modul 1-Anwendung aus dem Repository. Unabhängig davon, ob Sie Ihren oder unseren verwenden, starten wir im Code für Modul 1. In diesem Codelab werden Sie Schritt für Schritt durch die einzelnen Schritte geführt. Abschließend erhalten Sie Code, der dem im Repository-Ordner „FINISH“ des Moduls 7 enthaltenen Ordner ähnelt.

Unabhängig davon, welche Anwendung für Modul 1 Sie verwenden, sollte der Ordner so aussehen, möglicherweise auch mit einem lib-Ordner:

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

3. Referenz-App noch einmal bereitstellen

Führen Sie die folgenden Schritte aus, um die Anwendung „Modul 1“ (noch einmal) bereitzustellen:

  1. Löschen Sie den Ordner lib, falls vorhanden, und führen Sie pip install -t lib -r requirements.txt aus, um lib neu zu füllen. Wenn Sie Python 2 und 3 installiert haben, müssen Sie stattdessen möglicherweise den Befehl pip2 verwenden.
  2. Prüfen Sie, ob Sie das gcloud-Befehlszeilentool installiert und initialisiert und seine Nutzung überprüft haben.
  3. Legen Sie gcloud config set project PROJECT_ID für Ihr Cloud-Projekt fest, wenn Sie PROJECT_ID nicht bei jedem gcloud-Befehl eingeben möchten.
  4. Beispielanwendung mit gcloud app deploy bereitstellen
  5. Prüfen, ob die App für Modul 1 wie erwartet ausgeführt wird, ohne dass die letzten Besuche angezeigt werden (siehe Abbildung unten)

a7a9d2b80d706a2b.png

4. Konfiguration aktualisieren

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

5. Anwendungsdateien ändern

Die primäre Anwendungsdatei ist main.py und alle in diesem Abschnitt genannten Updates beziehen sich auf diese Datei. Außerdem wurde ein kleines Update an der Webvorlage templates/index.html vorgenommen. Folgende Änderungen sind in diesem Abschnitt zu implementieren:

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

1. Importe aktualisieren

Ein Import von google.appengine.api.taskqueue bietet die Funktionalität der Aufgabenwarteschlange. Einige Pakete der Python-Standardbibliothek sind ebenfalls erforderlich:

  • Da wir eine Aufgabe zum Löschen der ältesten Besuche hinzufügen, muss sich die App um Zeitstempel kümmern, also um die Verwendung von time und datetime.
  • Um nützliche Informationen zur Ausführung von Aufgaben zu protokollieren, benötigen wir logging.

Wenn Sie alle diese Importe hinzufügen, sehen Sie Ihren Code vor und nach diesen Änderungen:

VORHER:

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

NACHHER:

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 sortieren, neue Aufgabe in die Warteschlange stellen)

Die Dokumentation der Push-Warteschlange besagt: "Um eine Aufgabe zu verarbeiten, müssen Sie sie zu einer Push-Warteschlange hinzufügen. App Engine stellt eine Standard-Push-Warteschlange mit dem Namen default bereit, die konfiguriert ist und mit den Standardeinstellungen verwendet werden kann. Wenn Sie möchten, können Sie einfach alle Ihre Aufgaben zur Standardwarteschlange hinzufügen, ohne andere Warteschlangen erstellen und konfigurieren zu müssen.“ In diesem Codelab wird der Einfachheit halber die Warteschlange default verwendet. Weitere Informationen zum Definieren eigener Push-Warteschlangen mit denselben oder unterschiedlichen Eigenschaften finden Sie in der Dokumentation zum Erstellen von Push-Warteschlangen.

Das Hauptziel dieses Codelabs besteht darin, der Push-Warteschlange default eine Aufgabe hinzuzufügen, deren Aufgabe darin besteht, alte Besuche aus Datastore zu löschen, die nicht mehr angezeigt werden. Die Referenz-App registriert jeden Besuch (GET-Anfrage an /), indem sie eine neue Visit-Entität erstellt, ruft dann die letzten Besuche ab und zeigt sie an. Keiner der ältesten Besuche wird angezeigt oder noch einmal verwendet. Daher werden bei der Push-Aufgabe alle Besuche gelöscht, die älter als die ältesten angezeigten Besuche sind. Dazu muss sich das Verhalten der App ein wenig ändern:

  1. Wenn Sie die letzten Besuche abfragen, sollten Sie die App so ändern, dass der Zeitstempel der letzten Visit (ältesten angezeigten Besuche) gespeichert wird, anstatt diese Besuche sofort zurückzugeben. Sie können bedenkenlos alle Besuche löschen, die älter sind als dieser.
  2. Erstellen Sie eine Push-Aufgabe mit diesem Zeitstempel als Nutzlast und leiten Sie sie an den Aufgaben-Handler weiter, auf den über eine HTTP-POST an /trim zugegriffen werden kann. Verwenden Sie insbesondere Python-Standarddienstprogramme, um den Datenspeicherzeitstempel zu konvertieren und als Gleitkommazahl an die Aufgabe zu senden, aber auch als String zu protokollieren und als Sentinel-Wert zurückzugeben, der dem Nutzer angezeigt wird.

All dies findet in fetch_visits() statt und sieht so aus, wie es vor und nach diesen Aktualisierungen aussieht:

VORHER:

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

NACHHER:

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)

Während das Löschen alter Besuche in fetch_visits() möglich gewesen wäre, haben diese Funktionen nicht viel mit dem Endnutzer zu tun. Dabei handelt es sich um eine Zusatzfunktion, die für die asynchrone Verarbeitung außerhalb von Standard-App-Anfragen geeignet ist. Der Endnutzer wird von schnelleren Abfragen profitieren, da in Datastore weniger Informationen zur Verfügung stehen. Erstellen Sie eine neue Funktion trim(), die über eine POST-Anfrage aus der Aufgabenwarteschlange an /trim aufgerufen wird, die Folgendes ausführt:

  1. Extrahiert den „ältesten Besuch“ Zeitstempel-Nutzlast
  2. Setzt eine Datastore-Abfrage aus, um alle Entitäten zu finden, die älter als dieser Zeitstempel sind.
  3. Sich für eine schnellere Version nur für Schlüssel entscheiden da keine tatsächlichen Nutzerdaten erforderlich sind.
  4. Protokolliert die Anzahl der zu löschenden Entitäten (einschließlich null).
  5. Ruft ndb.delete_multi() auf, um Entitäten zu löschen (übersprungen, wenn nicht).
  6. Gibt einen leeren String zusammen mit einem impliziten HTTP 200-Rückgabecode zurück.

Du kannst das alles unten im trim() ansehen. 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, sofern diese Variable vorhanden ist:

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

Fügen Sie dieses Snippet nach der angezeigten Besuchsliste, aber vor dem Schließen des Textes ein, sodass Ihre Vorlage wie folgt 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 dieses Codelab abgeschlossen. Dazu wird die App bereitgestellt und geprüft, ob sie wie vorgesehen und in allen ausgegebenen Ausgabedaten funktioniert. Führen Sie nach der App-Überprüfung alle Bereinigungsschritte durch und erwägen Sie die nächsten Schritte.

Anwendung bereitstellen und prüfen

Stellen Sie die Anwendung mit gcloud app deploy bereit. Die Ausgabe sollte mit der App für Modul 1 identisch sein, mit Ausnahme einer neuen Zeile am unteren Rand, in der angezeigt wird, welche Besuche gelöscht werden:

4aa8a2cb5f527079.png

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

Bereinigen

Allgemein

Falls Sie vorerst fertig sind, empfehlen wir Ihnen, Ihre App Engine-Anwendung zu deaktivieren, um Gebühren zu vermeiden. Wenn Sie jedoch weitere Tests oder Experimente durchführen möchten, bietet die App Engine-Plattform ein kostenloses Kontingent. Solange Sie diese Nutzungsstufe nicht überschreiten, sollten Ihnen keine Kosten in Rechnung gestellt werden. Das bezieht sich auf die Rechenleistung. Es können jedoch auch Gebühren für relevante App Engine-Dienste anfallen. Weitere Informationen finden Sie auf der Preisseite. Wenn diese Migration andere Cloud-Dienste betrifft, werden diese separat abgerechnet. Lesen Sie in beiden Fällen gegebenenfalls den Abschnitt „Speziell für dieses Codelab“. weiter unten.

Zur vollständigen Offenlegung fallen bei der Bereitstellung auf einer serverlosen Computing-Plattform von Google Cloud wie App Engine geringfügige Build- und Speicherkosten an. Für Cloud Build und Cloud Storage gibt es ein eigenes kostenloses Kontingent. Die Speicherung dieses Images verbraucht einen Teil dieses Kontingents. Möglicherweise leben Sie in einer Region, in der es keine solche kostenlose Stufe gibt. Achten Sie daher auf Ihre Speichernutzung, um potenzielle Kosten zu minimieren. Bestimmte Cloud Storage-„Ordner“ sollten Sie Folgendes überprüfen:

  • 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 Speicherlinks oben hängen von Ihrer PROJECT_ID- und *LOC*-Adresse ab, z. B. „us“ wenn Ihre App in den USA gehostet wird.

Wenn Sie jedoch nicht mit dieser Anwendung oder anderen verwandten Migrations-Codelabs fortfahren und alles vollständig löschen möchten, beenden Sie Ihr Projekt.

Nur für dieses Codelab

Die unten aufgeführten Dienste gelten nur für dieses Codelab. Weitere Informationen finden Sie in der Dokumentation des jeweiligen Produkts:

Nächste Schritte

Bei dieser „Migration“ Sie haben der Beispiel-App für Modul 1 die Verwendung von Push-Warteschlangen für Aufgabenwarteschlangen hinzugefügt, um die Besucherverfolgung zu unterstützen. Daraus ergibt sich die Beispiel-App für Modul 7. In der nächsten Migration erfahren Sie, wie Sie bei Bedarf ein Upgrade von App Engine-Push-Aufgaben auf Cloud Tasks durchführen. Ab Herbst 2021 müssen Nutzer beim Upgrade auf Python 3 nicht mehr zu Cloud Tasks migrieren. Mehr dazu erfahren Sie im nächsten Abschnitt.

Wenn Sie zu Cloud Tasks wechseln möchten, finden Sie als Nächstes das Codelab für Modul 8. Darüber hinaus sind weitere Migrationen zu berücksichtigen, z. B. Cloud Datastore, Cloud Memorystore, Cloud Storage oder Cloud Pub/Sub (Pull-Warteschlangen). Außerdem werden produktübergreifende Migrationen zu Cloud Run und Cloud Functions durchgeführt. Auf alle Inhalte der serverlosen Migrationsstation (Codelabs, Videos, Quellcode [falls verfügbar]) kann über das Open-Source-Repository zugegriffen werden.

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 erweitert, die ursprünglich nur in Laufzeiten der 1. Generation verfügbar waren. Das bedeutet, dass Sie bei der Portierung Ihrer Anwendung zu Python 3 nicht mehr von gebündelten Diensten wie App Engine Task Queue zu eigenständigen Cloud- oder Drittanbieter-Entsprechungen wie Cloud Tasks migrieren müssen. Das heißt, Sie können die Aufgabenwarteschlange in App Engine-Anwendungen in Python 3 weiterhin verwenden, solange Sie den Code so überarbeiten, dass aus Laufzeiten der nächsten Generation auf gebündelte Dienste zugegriffen wird.

Weitere Informationen zur Migration gebündelter Dienste zu Python 3 finden Sie im Codelab zu Modul 17 und im entsprechenden Video. Während dieses Thema nicht für Modul 7 vorgesehen ist, finden Sie unten einen Link zu Python 3-Versionen der Anwendungen in Modul 1 und 7, die in Python 3 portiert wurden und noch App Engine NDB und Aufgabenwarteschlange verwenden.

8. Zusätzliche Ressourcen

Im Folgenden finden Sie zusätzliche Ressourcen für Entwickler, die sich näher mit diesem oder verwandten Migrationsmodul und ähnlichen Produkten befassen. 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.

Codelab-Probleme/Feedback

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

Migrationsressourcen

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

Codelab

Python 2

Python 3

Modul 1

code

code (in dieser Anleitung nicht enthalten)

Modul 7 (dieses Codelab)

code

code (in dieser Anleitung nicht enthalten)

Online-Ressourcen

Nachfolgend finden Sie Onlineressourcen, die für diese Anleitung relevant sein könnten:

App Engine-Aufgabenwarteschlange

App Engine-Plattform

Weitere Cloud-Informationen

Videos

Lizenz

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