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 wird Python 2-App Engine-Entwicklern gezeigt, wie sie Pull-Aufgaben aus App Engine-Aufgabenwarteschlangen zu Cloud Pub/Sub migrieren. Außerdem gibt es eine implizite Migration von App Engine NDB zu Cloud NDB für den Datastore-Zugriff (hauptsächlich in Modul 2 behandelt) sowie ein Upgrade auf Python 3.
In Modul 18 erfahren Sie, wie Sie die Verwendung von Pull-Aufgaben in Ihre App einfügen. In diesem Modul migrieren Sie die Verwendung in der fertigen App aus Modul 18 zu Cloud Pub/Sub. Nutzer, die Aufgabenwarteschlangen für Push-Aufgaben verwenden, migrieren stattdessen zu Cloud Tasks und sollten sich die Module 7 bis 9 ansehen.
Lerninhalte
- App Engine Task Queue (Pull-Aufgaben) durch Cloud Pub/Sub ersetzen
- Ersetzen Sie die Verwendung von App Engine NDB durch Cloud NDB (siehe auch Modul 2).
- App zu Python 3 portieren
Voraussetzungen
- Ein Google Cloud Platform-Projekt mit einem aktiven GCP-Rechnungskonto
- Grundlegende Python-Kenntnisse
- Grundkenntnisse zu gängigen Linux-Befehlen
- Grundlegende Kenntnisse zur Entwicklung und Bereitstellung von App Engine-Anwendungen
- Eine funktionierende App Engine-Beispielanwendung für Modul 18
Umfrage
Wie werden Sie diese Anleitung verwenden?
Wie würden Sie Ihre Erfahrung mit Python bewerten?
Wie würden Sie Ihre Erfahrungen mit Google Cloud-Diensten bewerten?
2. Hintergrund
Die App Engine Task Queue unterstützt sowohl Push- als auch Pull-Aufgaben. Um die Portabilität von Anwendungen zu verbessern, empfiehlt Google Cloud, von gebündelten Legacy-Diensten wie Task Queue zu anderen eigenständigen Cloud- oder Drittanbieterdiensten zu migrieren.
- Nutzer von Aufgabenwarteschlangen mit Push-Aufgaben�
- Nutzer von Aufgabenwarteschlangen-Pull-Aufgaben sollten zu Cloud Pub/Sub migrieren.
In den Modulen 7 bis 9 wird die Migration von Push-Aufgaben behandelt, in den Modulen 18 und 19 die Migration von Pull-Aufgaben. Cloud Tasks entspricht Push-Aufgaben in Task Queues eher, während Pub/Sub kein so enges Analogon zu Pull-Aufgaben in Task Queues ist.
Pub/Sub bietet mehr Funktionen als die Pull-Funktion der Aufgabenwarteschlange. Pub/Sub bietet beispielsweise auch Push-Funktionen. Cloud Tasks ähnelt jedoch eher Push-Aufgaben für Aufgabenwarteschlangen. Daher wird Pub/Sub-Push von keinem der Migrationsmodule abgedeckt. In diesem Codelab für Modul 19 wird gezeigt, wie der Warteschlangenmechanismus von Pull-Warteschlangen für Aufgabenwarteschlangen zu Pub/Sub umgestellt und von App Engine NDB zu Cloud NDB für den Datastore-Zugriff migriert wird. Dabei wird die Migration aus Modul 2 wiederholt.
Der Code aus Modul 18 wird zwar als Python 2-Beispielanwendung „beworben“, der Quellcode selbst ist jedoch mit Python 2 und 3 kompatibel. Das bleibt auch nach der Migration zu Cloud Pub/Sub (und Cloud NDB) in diesem Modul 19 so.
Diese Anleitung umfasst die folgenden Schritte:
- Einrichtung/Vorbereitung
- Konfiguration aktualisieren
- Anwendungscode ändern
3. Einrichtung/Vorbereitung
In diesem Abschnitt wird Folgendes erläutert:
- Cloud-Projekt einrichten
- Beispiel-App für die Baseline abrufen
- Ausgangsanwendung (neu) bereitstellen und validieren
- Neue Google Cloud-Dienste/APIs aktivieren
Mit diesen Schritten stellen Sie sicher, dass Sie mit funktionierendem Code beginnen und dass dieser für die Migration zu Cloud-Diensten bereit ist.
1. Projekt einrichten
Wenn Sie das Codelab zu Modul 18 abgeschlossen haben, können Sie dasselbe Projekt (und denselben Code) wiederverwenden. Alternativ können Sie ein neues Projekt erstellen oder ein anderes vorhandenes Projekt wiederverwenden. Prüfen Sie, ob das Projekt ein aktives Abrechnungskonto und eine aktivierte App Engine-Anwendung hat. Suchen Sie die Projekt-ID, da Sie sie in diesem Codelab benötigen. Verwenden Sie sie immer, wenn Sie auf die Variable PROJECT_ID stoßen.
2. Beispiel-App für die Baseline abrufen
Eine der Voraussetzungen ist eine funktionierende App Engine-App aus Modul 18. Sie können entweder das Codelab dazu durcharbeiten (empfohlen; Link oben) oder den Code aus Modul 18 aus dem Repository kopieren. Ganz gleich, ob Sie Ihre oder unsere verwenden – hier beginnen wir („START“). In diesem Codelab wird die Migration beschrieben. Am Ende des Codelabs finden Sie Code, der dem im Repo-Ordner von Modul 19 („FINISH“) ähnelt.
- START: Ordner „Modul 18“ (Python 2)
- ABSCHLUSS: Ordner „Modul 19“ (Python 2 und 3)
- Gesamtes Repository (zum Klonen oder Herunterladen einer ZIP-Datei)
Unabhängig davon, welche App aus Modul 18 Sie verwenden, sollte der Ordner so aussehen wie unten, möglicherweise auch mit einem Ordner lib:
$ ls README.md appengine_config.py queue.yaml templates app.yaml main.py requirements.txt
3. Ausgangsanwendung (neu) bereitstellen und validieren
Führen Sie die folgenden Schritte aus, um die App für Modul 18 bereitzustellen:
- Löschen Sie den Ordner
lib, falls er vorhanden ist, und führen Siepip install -t lib -r requirements.txtaus, umlibneu zu füllen. Möglicherweise müssen Siepip2verwenden, wenn sowohl Python 2 als auch Python 3 auf Ihrem Entwicklungscomputer installiert sind. - Achten Sie darauf, dass Sie das
gcloud-Befehlszeilentool installiert und initialisiert haben und sich mit der Verwendung vertraut gemacht haben. - Optional: Legen Sie Ihr Cloud-Projekt mit
gcloud config set projectPROJECT_IDfest, wenn SiePROJECT_IDnicht bei jedemgcloud-Befehl eingeben möchten. - Beispiel-App mit
gcloud app deploybereitstellen - Prüfen Sie, ob die App wie erwartet und ohne Probleme ausgeführt wird. Wenn Sie das Codelab zu Modul 18 abgeschlossen haben, werden in der App die wichtigsten Besucher und die letzten Besuche angezeigt (siehe Abbildung unten). Andernfalls sind möglicherweise keine Besucherzahlen vorhanden, die angezeigt werden können.

Bevor Sie die Beispiel-App aus Modul 18 migrieren, müssen Sie zuerst die Cloud-Dienste aktivieren, die von der geänderten App verwendet werden.
4. Neue Google Cloud-Dienste/APIs aktivieren
Die alte App hat gebündelte App Engine-Dienste verwendet, für die keine zusätzliche Einrichtung erforderlich ist. Für eigenständige Cloud-Dienste ist dies jedoch erforderlich. Die aktualisierte App verwendet sowohl Cloud Pub/Sub als auch Cloud Datastore (über die Cloud NDB-Clientbibliothek). App Engine und beide Cloud-APIs haben Kontingente für die kostenlose Stufe. Solange Sie diese Limits nicht überschreiten, sollten für diese Anleitung keine Gebühren anfallen. Cloud-APIs können je nach Bedarf über die Cloud Console oder über die Befehlszeile aktiviert werden.
Über die Cloud Console
Rufen Sie in der Cloud Console die Seite API Manager's Library (für das richtige Projekt) auf und suchen Sie in der Suchleiste in der Mitte der Seite nach den Cloud Datastore- und Cloud Pub/Sub-APIs:

Klicken Sie für jede API separat auf die Schaltfläche Aktivieren. Möglicherweise werden Sie aufgefordert, Zahlungsinformationen anzugeben. Hier sehen Sie beispielsweise die Seite „Cloud Pub/Sub API Library“:

Über die Befehlszeile
Das Aktivieren von APIs über die Konsole ist zwar visuell informativ, aber einige Nutzer bevorzugen die Befehlszeile. Führen Sie den Befehl gcloud services enable pubsub.googleapis.com datastore.googleapis.com aus, um beide APIs gleichzeitig zu aktivieren:
$ gcloud services enable pubsub.googleapis.com datastore.googleapis.com Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.
Möglicherweise werden Sie aufgefordert, Zahlungsinformationen anzugeben. Wenn Sie andere Cloud APIs aktivieren möchten und wissen möchten, welche URIs sie haben, finden Sie diese unten auf der Bibliotheksseite der jeweiligen API. Beachten Sie beispielsweise pubsub.googleapis.com als „Dienstname“ unten auf der Pub/Sub-Seite oben.
Danach kann Ihr Projekt auf die APIs zugreifen. Jetzt ist es an der Zeit, die Anwendung zu aktualisieren, damit sie diese APIs verwendet.
4. Pub/Sub-Ressourcen erstellen
Zusammenfassung der Reihenfolge des Task Queue-Workflows aus Modul 18:
- In Modul 18 wurde die Datei
queue.yamlverwendet, um eine Pull-Warteschlange mit dem Namenpullqzu erstellen. - Die App fügt der Pull-Warteschlange Aufgaben hinzu, um Besucher zu erfassen.
- Aufgaben werden schließlich von einem Worker verarbeitet, der für eine begrenzte Zeit (eine Stunde) freigegeben wird.
- Aufgaben werden ausgeführt, um die Anzahl der letzten Besucher zu ermitteln.
- Aufgaben werden nach Abschluss aus der Warteschlange gelöscht.
Sie werden einen ähnlichen Workflow mit Pub/Sub nachbilden. Im nächsten Abschnitt werden die grundlegenden Pub/Sub-Begriffe eingeführt und drei verschiedene Möglichkeiten zum Erstellen der erforderlichen Pub/Sub-Ressourcen beschrieben.
App Engine Task Queue (Pull) – Terminologie im Vergleich zu Cloud Pub/Sub
Für die Umstellung auf Pub/Sub ist eine geringfügige Anpassung des Vokabulars erforderlich. Unten sind die primären Kategorien mit relevanten Begriffen aus beiden Produkten aufgeführt. Sehen Sie sich auch den Migrationsleitfaden an, in dem ähnliche Vergleiche enthalten sind.
- Datenstruktur für die Warteschlange:Bei Task Queue werden die Daten in Pull-Warteschlangen eingefügt, bei Pub/Sub in Themen.
- Einheiten von in die Warteschlange gestellten Daten : Pull-Aufgaben mit Task Queue werden mit Pub/Sub als Nachrichten bezeichnet.
- Datenverarbeiter:Bei Task Queue greifen Worker auf Pull-Aufgaben zu. Bei Pub/Sub benötigen Sie Abos/Abonnenten, um Nachrichten zu empfangen.
- Datenextraktion : Das Leasen einer Pull-Aufgabe entspricht dem Abrufen einer Nachricht aus einem Thema (über ein Abo).
- Bereinigung/Abschluss : Das Löschen einer Task Queues-Aufgabe aus einer Pull-Warteschlange, wenn Sie fertig sind, entspricht dem Bestätigen einer Pub/Sub-Nachricht.
Obwohl sich das Produkt für die Warteschlange ändert, bleibt der Workflow relativ ähnlich:
- Anstelle einer Pull-Warteschlange verwendet die App ein Thema namens
pullq. - Anstatt Aufgaben in eine Pull-Warteschlange einzufügen, sendet die App Nachrichten an ein Thema (
pullq). - Anstatt dass ein Worker Aufgaben aus der Pull-Warteschlange leiht, ruft ein Abonnent namens
workerNachrichten aus dem Themapullqab. - Die App verarbeitet Nutzlasten von Nachrichten und erhöht die Besucherzahlen im Datastore.
- Anstatt Aufgaben aus der Pull-Warteschlange zu löschen, bestätigt die App die verarbeiteten Nachrichten.
Bei der Aufgabenwarteschlange müssen Sie die Pull-Warteschlange erstellen. Bei Pub/Sub müssen Sie sowohl ein Thema als auch ein Abo erstellen. In Modul 18 haben wir queue.yaml außerhalb der App-Ausführung verarbeitet. Das muss jetzt auch mit Pub/Sub geschehen.
Es gibt drei Möglichkeiten, Themen und Abos zu erstellen:
- Über die Cloud Console
- Über die Befehlszeile
- Über Code (kurzes Python-Script)
Wählen Sie eine der folgenden Optionen aus und folgen Sie der entsprechenden Anleitung, um Ihre Pub/Sub-Ressourcen zu erstellen.
Über die Cloud Console
So erstellen Sie ein Thema über die Cloud Console:
- Rufen Sie in der Cloud Console die Seite Pub/Sub-Themen auf.
- Klicken Sie oben auf Thema erstellen. Ein neues Dialogfeld wird geöffnet (siehe Abbildung unten).
- Geben Sie im Feld Themen-ID den Wert
pullqein. - Entfernen Sie die Häkchen aus allen ausgewählten Optionen und wählen Sie Von Google verwalteter Verschlüsselungsschlüssel aus.
- Klicken Sie auf die Schaltfläche Thema erstellen.
So sieht das Dialogfeld zum Erstellen von Themen aus:

Nachdem Sie ein Thema erstellt haben, muss ein Abo für dieses Thema erstellt werden:
- Rufen Sie in der Cloud Console die Seite Pub/Sub-Abos auf.
- Klicken Sie oben auf Abo erstellen (siehe Abbildung unten).
- Geben Sie
workerin das Feld Abo-ID ein. - Wählen Sie
pullqaus dem Drop-down-Menü Cloud Pub/Sub-Thema auswählen aus und notieren Sie den vollständig qualifizierten Pfadnamen, z. B.projects/PROJECT_ID/topics/pullq. - Wählen Sie als Zustellungstyp Pull aus.
- Lassen Sie alle anderen Optionen unverändert und klicken Sie auf die Schaltfläche Erstellen.
So sieht der Bildschirm zur Aboerstellung aus:

Sie können ein Abo auch auf der Seite Themen erstellen. Diese „Verknüpfung“ kann nützlich sein, um Themen mit Abos zu verknüpfen. Weitere Informationen zum Erstellen von Abos finden Sie in der Dokumentation.
Über die Befehlszeile
Pub/Sub-Nutzer können Themen und Abos mit den Befehlen gcloud pubsub topics create TOPIC_ID und gcloud pubsub subscriptions create SUBSCRIPTION_ID --topic=TOPIC_ID erstellen. Wenn Sie diese mit einem TOPIC_ID von pullq und einem SUBSCRIPTION_ID von worker ausführen, erhalten Sie die folgende Ausgabe für das Projekt PROJECT_ID:
$ gcloud pubsub topics create pullq Created topic [projects/PROJECT_ID/topics/pullq]. $ gcloud pubsub subscriptions create worker --topic=pullq Created subscription [projects/PROJECT_ID/subscriptions/worker].
Weitere Informationen finden Sie auf dieser Seite in der Schnellstartanleitung. Die Verwendung der Befehlszeile kann Workflows vereinfachen, in denen Themen und Abos regelmäßig erstellt werden. Zu diesem Zweck können solche Befehle in Shell-Skripts verwendet werden.
Über Code (kurzes Python-Script)
Eine weitere Möglichkeit, das Erstellen von Themen und Abos zu automatisieren, ist die Verwendung der Pub/Sub API im Quellcode. Unten sehen Sie den Code für das maker.py-Skript im Repo-Ordner für Modul 19.
from __future__ import print_function
import google.auth
from google.api_core import exceptions
from google.cloud import pubsub
_, PROJECT_ID = google.auth.default()
TOPIC = 'pullq'
SBSCR = 'worker'
ppc_client = pubsub.PublisherClient()
psc_client = pubsub.SubscriberClient()
TOP_PATH = ppc_client.topic_path(PROJECT_ID, TOPIC)
SUB_PATH = psc_client.subscription_path(PROJECT_ID, SBSCR)
def make_top():
try:
top = ppc_client.create_topic(name=TOP_PATH)
print('Created topic %r (%s)' % (TOPIC, top.name))
except exceptions.AlreadyExists:
print('Topic %r already exists at %r' % (TOPIC, TOP_PATH))
def make_sub():
try:
sub = psc_client.create_subscription(name=SUB_PATH, topic=TOP_PATH)
print('Subscription created %r (%s)' % (SBSCR, sub.name))
except exceptions.AlreadyExists:
print('Subscription %r already exists at %r' % (SBSCR, SUB_PATH))
try:
psc_client.close()
except AttributeError: # special Py2 handler for grpcio<1.12.0
pass
make_top()
make_sub()
Die Ausführung dieses Skripts führt zur erwarteten Ausgabe (sofern keine Fehler auftreten):
$ python3 maker.py Created topic 'pullq' (projects/PROJECT_ID/topics/pullq) Subscription created 'worker' (projects/PROJECT_ID/subscriptions/worker)
Wenn Sie die API aufrufen, um bereits vorhandene Ressourcen zu erstellen, wird von der Clientbibliothek eine google.api_core.exceptions.AlreadyExists-Ausnahme ausgelöst, die vom Skript ordnungsgemäß verarbeitet wird:
$ python3 maker.py Topic 'pullq' already exists at 'projects/PROJECT_ID/topics/pullq' Subscription 'worker' already exists at 'projects/PROJECT_ID/subscriptions/worker'
Wenn Sie Pub/Sub noch nicht kennen, finden Sie im Pub/Sub-Architektur-Whitepaper weitere Informationen.
5. Konfiguration aktualisieren
Konfigurationsänderungen umfassen sowohl das Ändern verschiedener Konfigurationsdateien als auch das Erstellen von App Engine-Pull-Warteschlangen, jedoch innerhalb des Cloud Pub/Sub-Ökosystems.
queue.yaml löschen
Wir stellen die Aufgabenwarteschlange vollständig ein. Löschen Sie daher queue.yaml, da diese Datei von Pub/Sub nicht verwendet wird. Anstatt eine Pull-Warteschlange zu erstellen, erstellen Sie ein Pub/Sub-Thema (und ein Abo).
requirements.txt
Hängen Sie sowohl google-cloud-ndb als auch google-cloud-pubsub an requirements.txt an, um flask aus Modul 18 zusammenzuführen. Ihr aktualisiertes Modul 19 requirements.txt sollte nun so aussehen:
flask
google-cloud-ndb
google-cloud-pubsub
Diese requirements.txt-Datei enthält keine Versionsnummern. Daher sind die neuesten Versionen ausgewählt. Sollten Inkompatibilitäten auftreten, folgen Sie der Standardvorgehensweise, Versionsnummern zu verwenden, um funktionierende Versionen für eine App festzulegen.
app.yaml
Die Änderungen an app.yaml hängen davon ab, ob Sie bei Python 2 bleiben oder auf Python 3 umstellen.
Python 2
Durch die oben genannte Aktualisierung von requirements.txt werden Google Cloud-Clientbibliotheken verwendet. Dafür ist zusätzliche Unterstützung von App Engine erforderlich, nämlich einige integrierte Bibliotheken, setuptools und grpcio. Für die Verwendung integrierter Bibliotheken ist ein libraries-Abschnitt in app.yaml und Bibliotheksversionsnummern oder „latest“ für die neueste auf App Engine-Servern verfügbare Version erforderlich. Modul 18 app.yaml enthält noch keinen dieser Abschnitte:
VORHER:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
Fügen Sie app.yaml einen libraries-Abschnitt mit Einträgen für setuptools und grpcio hinzu und wählen Sie die jeweils aktuelle Version aus. Fügen Sie außerdem einen Platzhalter runtime für Python 3 hinzu, der zusammen mit einer aktuellen 3.x-Version (z. B. 3.10 zum Zeitpunkt der Erstellung dieses Dokuments) auskommentiert wird. Nach diesen Änderungen sieht app.yaml so aus:
DANACH:
#runtime: python310
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: setuptools
version: latest
- name: grpcio
version: latest
Python 3
Für Python 3-Nutzer und app.yaml geht es vor allem darum, Dinge zu entfernen. In diesem Abschnitt löschen Sie den Abschnitt handlers, die Direktiven threadsafe und api_version und erstellen keinen Abschnitt libraries.
Laufzeiten der zweiten Generation bieten keine integrierten Drittanbieterbibliotheken. Daher ist in app.yaml kein libraries-Abschnitt erforderlich. Außerdem ist das Kopieren (manchmal auch als Vendoring oder Self-Bundling bezeichnet) nichtintegrierter Drittanbieterpakete nicht mehr erforderlich. Sie müssen nur Drittanbieterbibliotheken auflisten, die von Ihrer App in requirements.txt verwendet werden.
Im Abschnitt handlers in app.yaml werden Anwendungs- (Skript-) und Handler für statische Dateien angegeben. Da die Python 3-Laufzeit erfordert, dass Web-Frameworks ihr eigenes Routing ausführen, müssen alle Skript-Handler in auto geändert werden. Wenn Ihre App (wie in Modul 18) keine statischen Dateien bereitstellt, wären alle Routen auto und somit irrelevant. Daher ist auch der handlers-Abschnitt nicht erforderlich. Löschen Sie ihn.
Schließlich werden weder die threadsafe- noch die api_version-Direktiven in Python 3 verwendet. Löschen Sie sie also auch. Sie sollten alle Abschnitte von app.yaml löschen, sodass nur die runtime-Anweisung mit einer modernen Version von Python 3, z. B. 3.10, übrig bleibt. So sieht app.yaml vor und nach diesen Änderungen aus:
VORHER:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
DANACH:
runtime: python310
Für diejenigen, die noch nicht bereit sind, alles aus ihrem app.yaml für Python 3 zu löschen, haben wir eine alternative Datei app3.yaml im Repo-Ordner für Modul 19 bereitgestellt. Wenn Sie diese Datei stattdessen für Bereitstellungen verwenden möchten, hängen Sie den Dateinamen an das Ende des Befehls an: gcloud app deploy app3.yaml. Andernfalls wird standardmäßig die unveränderte Python 2-Datei app.yaml verwendet und Ihre App damit bereitgestellt.
appengine_config.py
Wenn Sie ein Upgrade auf Python 3 durchführen, ist appengine_config.py nicht erforderlich. Löschen Sie es daher. Das ist nicht erforderlich, da für die Unterstützung von Drittanbieterbibliotheken nur die Angabe in requirements.txt erforderlich ist. Python 2-Nutzer lesen bitte weiter.
Das Modul 18 appengine_config.py enthält den entsprechenden Code zur Unterstützung von Drittanbieterbibliotheken, z. B. Flask und die Cloud-Clientbibliotheken, die gerade zu requirements.txt hinzugefügt wurden:
VORHER:
from google.appengine.ext import vendor
# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
Dieser Code allein reicht jedoch nicht aus, um die gerade hinzugefügten integrierten Bibliotheken (setuptools, grpcio) zu unterstützen. Es sind noch einige Zeilen erforderlich. Aktualisieren Sie appengine_config.py so, dass es so aussieht:
DANACH:
import pkg_resources
from google.appengine.ext import vendor
# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
# Add libraries to pkg_resources working set to find the distribution.
pkg_resources.working_set.add_entry(PATH)
Weitere Informationen zu den Änderungen, die für die Unterstützung von Cloud-Clientbibliotheken erforderlich sind, finden Sie in der Dokumentation zur Migration gebündelter Dienste.
Weitere Konfigurationsupdates
Wenn Sie einen lib-Ordner haben, löschen Sie ihn. Wenn Sie Python 2 verwenden, füllen Sie den Ordner lib mit dem folgenden Befehl wieder auf:
pip install -t lib -r requirements.txt # or pip2
Wenn Sie sowohl Python 2 als auch Python 3 auf Ihrem Entwicklungssystem installiert haben, müssen Sie möglicherweise pip2 anstelle von pip verwenden.
6. Anwendungscode ändern
In diesem Abschnitt werden Aktualisierungen der Hauptanwendungsdatei main.py beschrieben, bei denen die Verwendung von App Engine Task Queue-Pull-Warteschlangen durch Cloud Pub/Sub ersetzt wird. An der Webvorlage templates/index.html wurden keine Änderungen vorgenommen. Beide Apps sollten identisch funktionieren und dieselben Daten anzeigen.
Importe und Initialisierung aktualisieren
Es gibt mehrere Änderungen an Importen und der Initialisierung:
- Ersetzen Sie für die Importe App Engine NDB und Task Queue durch Cloud NDB und Pub/Sub.
- Benennen Sie
pullqvon einemQUEUE-Namen in einenTOPIC-Namen um. - Bei Pull-Aufgaben hat der Worker sie für eine Stunde geleast. Bei Pub/Sub werden Zeitüberschreitungen jedoch pro Nachricht gemessen. Löschen Sie daher die Konstante
HOUR. - Für Cloud APIs ist die Verwendung eines API-Clients erforderlich. Initialisieren Sie diese daher für Cloud NDB und Cloud Pub/Sub. Letztere bietet Clients für Themen und Abos.
- Für Pub/Sub ist die Cloud-Projekt-ID erforderlich. Importieren Sie sie daher aus
google.auth.default()und rufen Sie sie ab. - Für Pub/Sub sind „vollständig qualifizierte Pfadnamen“ für Themen und Abos erforderlich. Erstellen Sie diese daher mit den
*_path()-Hilfsfunktionen.
Unten sehen Sie die Importe und die Initialisierung aus Modul 18 sowie die Abschnitte nach der Implementierung der oben genannten Änderungen. Der Großteil des neuen Codes besteht aus verschiedenen Pub/Sub-Ressourcen:
VORHER:
from flask import Flask, render_template, request
from google.appengine.api import taskqueue
from google.appengine.ext import ndb
HOUR = 3600
LIMIT = 10
TASKS = 1000
QNAME = 'pullq'
QUEUE = taskqueue.Queue(QNAME)
app = Flask(__name__)
DANACH:
from flask import Flask, render_template, request
import google.auth
from google.cloud import ndb, pubsub
LIMIT = 10
TASKS = 1000
TOPIC = 'pullq'
SBSCR = 'worker'
app = Flask(__name__)
ds_client = ndb.Client()
ppc_client = pubsub.PublisherClient()
psc_client = pubsub.SubscriberClient()
_, PROJECT_ID = google.auth.default()
TOP_PATH = ppc_client.topic_path(PROJECT_ID, TOPIC)
SUB_PATH = psc_client.subscription_path(PROJECT_ID, SBSCR)
Datenmodellaktualisierungen
Das Visit-Datenmodell ändert sich nicht. Für den Datastore-Zugriff ist die explizite Verwendung des Cloud NDB API-Clientkontextmanagers ds_client.context() erforderlich. Im Code bedeutet das, dass Sie Datastore-Aufrufe sowohl in store_visit() als auch in fetch_visits() innerhalb von Python-with-Blöcken einschließen. Dieses Update entspricht dem Inhalt von Modul 2.
Die wichtigste Änderung für Pub/Sub besteht darin, dass das Einreihen einer Pull-Aufgabe für die Aufgabenwarteschlange durch das Veröffentlichen einer Pub/Sub-Nachricht im Thema pullq ersetzt wird. Unten sehen Sie den Code vor und nach diesen Änderungen:
VORHER:
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
def store_visit(remote_addr, user_agent):
'create new Visit in Datastore and queue request to bump visitor count'
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
QUEUE.add(taskqueue.Task(payload=remote_addr, method='PULL'))
def fetch_visits(limit):
'get most recent visits'
return Visit.query().order(-Visit.timestamp).fetch(limit)
DANACH:
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
def store_visit(remote_addr, user_agent):
'create new Visit in Datastore and queue request to bump visitor count'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
ppc_client.publish(TOP_PATH, remote_addr.encode('utf-8'))
def fetch_visits(limit):
'get most recent visits'
with ds_client.context():
return Visit.query().order(-Visit.timestamp).fetch(limit)
Aktualisierungen des Datenmodells „VisitorCount“
Das VisitorCount-Datenmodell ändert sich nicht und fetch_counts(), mit Ausnahme der Einbettung der Datastore-Abfrage in einen with-Block, wie unten dargestellt:
VORHER:
class VisitorCount(ndb.Model):
visitor = ndb.StringProperty(repeated=False, required=True)
counter = ndb.IntegerProperty()
def fetch_counts(limit):
'get top visitors'
return VisitorCount.query().order(-VisitorCount.counter).fetch(limit)
DANACH:
class VisitorCount(ndb.Model):
visitor = ndb.StringProperty(repeated=False, required=True)
counter = ndb.IntegerProperty()
def fetch_counts(limit):
'get top visitors'
with ds_client.context():
return VisitorCount.query().order(-VisitorCount.counter).fetch(limit)
Worker-Code aktualisieren
Der Worker-Code wird aktualisiert, indem NDB durch Cloud NDB und Task Queue durch Pub/Sub ersetzt werden. Der Workflow bleibt jedoch gleich.
- Schließen Sie Datastore-Aufrufe in den Cloud NDB-Kontextmanager-Block
withein. - Beim Bereinigen der Aufgabenwarteschlange werden alle Aufgaben aus der Pull-Warteschlange gelöscht. Bei Pub/Sub werden „Bestätigungs-IDs“ in
ackserfasst und dann am Ende gelöscht/bestätigt. - Task Queue-Pull-Aufgaben werden auf ähnliche Weise geleast wie Pub/Sub-Nachrichten abgerufen werden. Während Pull-Aufgaben mit den Aufgabenobjekten selbst gelöscht werden, werden Pub/Sub-Nachrichten über ihre Bestätigungs-IDs gelöscht.
- Für Pub/Sub-Nachrichtennutzlasten sind Bytes (nicht Python-Strings) erforderlich. Daher erfolgt beim Veröffentlichen in einem Thema bzw. beim Abrufen von Nachrichten aus einem Thema eine UTF-8-Codierung und -Decodierung.
Ersetzen Sie log_visitors() durch den aktualisierten Code unten, in dem die gerade beschriebenen Änderungen implementiert sind:
VORHER:
@app.route('/log')
def log_visitors():
'worker processes recent visitor counts and updates them in Datastore'
# tally recent visitor counts from queue then delete those tasks
tallies = {}
tasks = QUEUE.lease_tasks(HOUR, TASKS)
for task in tasks:
visitor = task.payload
tallies[visitor] = tallies.get(visitor, 0) + 1
if tasks:
QUEUE.delete_tasks(tasks)
# increment those counts in Datastore and return
for visitor in tallies:
counter = VisitorCount.query(VisitorCount.visitor == visitor).get()
if not counter:
counter = VisitorCount(visitor=visitor, counter=0)
counter.put()
counter.counter += tallies[visitor]
counter.put()
return 'DONE (with %d task[s] logging %d visitor[s])\r\n' % (
len(tasks), len(tallies))
DANACH:
@app.route('/log')
def log_visitors():
'worker processes recent visitor counts and updates them in Datastore'
# tally recent visitor counts from queue then delete those tasks
tallies = {}
acks = set()
rsp = psc_client.pull(subscription=SUB_PATH, max_messages=TASKS)
msgs = rsp.received_messages
for rcvd_msg in msgs:
acks.add(rcvd_msg.ack_id)
visitor = rcvd_msg.message.data.decode('utf-8')
tallies[visitor] = tallies.get(visitor, 0) + 1
if acks:
psc_client.acknowledge(subscription=SUB_PATH, ack_ids=acks)
try:
psc_client.close()
except AttributeError: # special handler for grpcio<1.12.0
pass
# increment those counts in Datastore and return
if tallies:
with ds_client.context():
for visitor in tallies:
counter = VisitorCount.query(VisitorCount.visitor == visitor).get()
if not counter:
counter = VisitorCount(visitor=visitor, counter=0)
counter.put()
counter.counter += tallies[visitor]
counter.put()
return 'DONE (with %d task[s] logging %d visitor[s])\r\n' % (
len(msgs), len(tallies))
Am Hauptanwendungs-Handler root() ändert sich nichts. Auch in der HTML-Vorlagendatei templates/index.html sind keine Änderungen erforderlich. Herzlichen Glückwunsch zur neuen Anwendung für Modul 19 mit Cloud Pub/Sub!
7. Zusammenfassung/Bereinigung
Stellen Sie Ihre App bereit, um zu prüfen, ob sie wie vorgesehen funktioniert und ob die Ausgabe korrekt ist. Führen Sie den Worker auch aus, um die Besucherzahlen zu verarbeiten. Führen Sie nach der App-Validierung alle erforderlichen Bereinigungsschritte aus und überlegen Sie sich, wie Sie weiter vorgehen möchten.
Anwendung bereitstellen und überprüfen
Prüfen Sie, ob Sie das Thema pullq und das Abo worker bereits erstellt haben. Wenn Sie das abgeschlossen haben und Ihre Beispiel-App bereit ist, stellen Sie Ihre App mit gcloud app deploy bereit. Die Ausgabe sollte mit der App aus Modul 18 identisch sein, mit der Ausnahme, dass Sie den gesamten zugrunde liegenden Mechanismus für die Warteschlange erfolgreich ersetzt haben:

Das Web-Frontend der App überprüft nun, ob dieser Teil der Anwendung funktioniert. In diesem Teil der App werden die wichtigsten Besucher und die letzten Besuche erfolgreich abgefragt und angezeigt. Allerdings wird dieser Besuch auch registriert und es wird eine Pull-Aufgabe erstellt, um diesen Besucher zur Gesamtzahl hinzuzufügen. Diese Aufgabe befindet sich jetzt in der Warteschlange und wartet auf die Verarbeitung.
Sie können dies mit einem App Engine-Backend-Dienst, einem cron-Job, durch Aufrufen von /log oder durch Senden einer HTTP-Anfrage über die Befehlszeile ausführen. Hier sehen Sie ein Beispiel für die Ausführung und Ausgabe des Worker-Codes mit curl (ersetzen Sie PROJECT_ID durch Ihre):
$ curl https://PROJECT_ID.appspot.com/log DONE (with 1 task[s] logging 1 visitor[s])
Die aktualisierte Anzahl wird dann beim nächsten Websitebesuch angezeigt. Geschafft!
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/imagesconsole.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com- Die oben genannten Speicherlinks hängen von Ihrem
PROJECT_IDund *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:
- Für verschiedene Komponenten von Cloud Pub/Sub gibt es eine kostenlose Stufe. Ermitteln Sie Ihre Gesamtnutzung, um einen besseren Überblick über die Kosten zu erhalten. Weitere Informationen finden Sie auf der Preisseite.
- Der Dienst App Engine Datastore wird von Cloud Datastore (Cloud Firestore im Datastore-Modus) bereitgestellt, das ebenfalls eine kostenlose Stufe bietet. Weitere Informationen finden Sie auf der Preisseite.
Nächste Schritte
Neben dieser Anleitung gibt es weitere Migrationsmodule, die sich mit der Umstellung von den gebündelten Legacy-Diensten befassen:
- Modul 2: Von App Engine
ndbzu Cloud NDB migrieren - Module 7–9: Migration von App Engine Task Queue (Push-Aufgaben) zu Cloud Tasks
- Module 12–13: Von App Engine Memcache zu Cloud Memorystore migrieren
- Module 15–16: Migration von App Engine Blobstore zu Cloud Storage
App Engine ist nicht mehr die einzige serverlose Plattform in Google Cloud. Wenn Sie eine kleine App Engine-Anwendung oder eine Anwendung mit eingeschränkter Funktionalität haben und sie in einen eigenständigen Mikrodienst umwandeln möchten oder eine monolithische Anwendung in mehrere wiederverwendbare Komponenten aufteilen möchten, sind dies gute Gründe für einen Wechsel zu Cloud Functions. Wenn die Containerisierung Teil Ihres Anwendungsentwicklungs-Workflows geworden ist, insbesondere wenn er aus einer CI/CD-Pipeline (Continuous Integration/Continuous Delivery oder Deployment) besteht, sollten Sie eine Migration zu Cloud Run in Betracht ziehen. Diese Szenarien werden in den folgenden Modulen behandelt:
- Von App Engine zu Cloud Functions migrieren: Modul 11
- Von App Engine zu Cloud Run migrieren: Modul 4 enthält Informationen zum Containerisieren Ihrer App mit Docker und Modul 5 zum Containerisieren ohne Container, Docker-Kenntnisse oder
Dockerfiles.
Der Wechsel zu einer anderen serverlosen Plattform ist optional. Wir empfehlen, die besten Optionen für Ihre Apps und Anwendungsfälle zu prüfen, bevor Sie Änderungen vornehmen.
Unabhängig davon, welches Migrationsmodul Sie als Nächstes in Betracht ziehen, können Sie auf alle Serverless Migration Station-Inhalte (Codelabs, Videos, Quellcode [sofern verfügbar]) über das zugehörige Open-Source-Repository zugreifen. Das README des Repositorys enthält auch Informationen dazu, welche Migrationen infrage kommen und welche Reihenfolge der Migrationsmodule relevant ist.
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 18 (START) und Modul 19 (FINISH) finden Sie in der Tabelle unten.
Codelab | Python 2 | Python 3 |
(n/a) | ||
Modul 19 (dieses Codelab) | (wie bei Python 2, außer dass Sie app3.yaml verwenden, sofern Sie app.yaml nicht wie oben beschrieben aktualisiert haben) |
Online-Referenzen
Unten finden Sie Ressourcen, die für diese Anleitung relevant sind:
App Engine-Aufgabenwarteschlange
- App Engine Task Queue – Übersicht
- App Engine-Aufgabenwarteschlangen – Übersicht über Pull-Warteschlangen
- App Engine-Beispielanwendung für Pull-Warteschlange für Task Queue
- Pull-Warteschlangen für die Aufgabenwarteschlange erstellen
- Google I/O 2011 – Einführungsvideo zur Pull-Warteschlange ( Votelator-Beispiel-App)
- Referenz zu
queue.yaml queue.yamlim Vergleich zu Cloud Tasks- Migrationsleitfaden für Pull-Warteschlangen zu Pub/Sub
Cloud Pub/Sub
- Cloud Pub/Sub-Produktseite
- Pub/Sub-Clientbibliotheken verwenden
- Beispiele für die Pub/Sub-Python-Clientbibliothek
- Pub/Sub-Dokumentation zur Python-Clientbibliothek
- Pub/Sub-Themen erstellen und verwalten
- Richtlinien für die Benennung von Pub/Sub-Themen
- Pub/Sub-Abos erstellen und verwalten
- App Engine-Beispielanwendung (flexibel) (kann auch in der Standardumgebung bereitgestellt werden; Python 3)
- Repository für die Beispiel-App oben
- Pub/Sub-Pull-Abos
- Pub/Sub-Push-Abos
- App Engine-Beispielanwendung für Pub/Sub-Push (Python 3)
- App Engine-Beispiel-App-Repository für Pub/Sub-Push
- Pub/Sub – Preise
- Cloud Tasks oder Cloud Pub/Sub? (Push im Vergleich zu Pull)
App Engine NDB und Cloud NDB (Datastore)
- App Engine NDB-Dokumentation
- App Engine NDB-Repository
- Google Cloud NDB-Dokumentation
- Google Cloud NDB-Repository
- Cloud Datastore-Preisinformationen
App Engine-Plattform
- App Engine-Dokumentation
- Python 2-Laufzeit für die App Engine-Standardumgebung
- Integrierte App Engine-Bibliotheken in Python 2 App Engine verwenden
- Python 3-Laufzeit für die App Engine-Standardumgebung
- Unterschiede zwischen den Python 2- und Python 3-Laufzeiten in App Engine (Standardumgebung)
- Migrationsanleitung für App Engine (Standardumgebung) von Python 2 zu Python 3
- Informationen zu Preisen und Kontingenten für App Engine
- Einführung der App Engine-Plattform der zweiten Generation (2018)
- Plattformen der ersten und zweiten Generation vergleichen
- Langfristiger Support für ältere Laufzeiten
- Beispiele für die Dokumentationsmigration
- Migrationsbeispiele der Community
Andere Cloud-Informationen
- Python auf der Google Cloud Platform
- Google Cloud Python-Clientbibliotheken
- Kostenlose Stufe von Google Cloud
- Google Cloud SDK (
gcloud-Befehlszeilentool) - Gesamte Google Cloud-Dokumentation
Videos
- Serverless Migration Station
- Serverless Expeditions
- Google Cloud Tech abonnieren
- Google Developers abonnieren
Lizenz
Dieser Text ist mit einer Creative Commons Attribution 2.0 Generic License lizenziert.