Von Pull-Aufgaben der App Engine-Aufgabenwarteschlange zu Cloud Pub/Sub migrieren (Modul 19)

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.

Zweck dieses Codelab ist es, App Engine-Entwicklern für Python 2 zu zeigen, wie sie von Pull-Aufgaben der App Engine-Aufgabenwarteschlange 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 Ihrer App die Verwendung von Pull-Aufgaben hinzufügen. In diesem Modul migrieren Sie die abgeschlossene Anwendung in Modul 18 zu Cloud Pub/Sub. Diejenigen, die Aufgabenwarteschlangen für Push-Aufgaben verwenden, migrieren stattdessen zu Cloud Tasks und sollten sich stattdessen auf die Module 7 bis 9 beziehen.

Sie werden lernen,

Voraussetzungen

Umfrage

Wie möchten Sie diese Anleitung nutzen?

<ph type="x-smartling-placeholder"></ph> Lesen Sie sie nur durch. 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. Um die Übertragbarkeit von Anwendungen zu verbessern, empfiehlt Google Cloud, von gebündelten Legacy-Diensten wie Task Queue zu anderen eigenständigen Cloud-Diensten oder gleichwertigen Drittanbieterdiensten zu migrieren.

In den Migrationsmodulen 7–9 geht es um die Migration von Push-Aufgaben, in den Modulen 18 bis 19 dagegen um die Migration von Pull-Aufgaben. Während Cloud Tasks bei Push-Aufgaben in Aufgabenwarteschlangen einen engeren Abgleich zwischen Aufgabenwarteschlangen-Push-Aufgaben durchführt, ist Pub/Sub weniger vergleichbar als Pull-Aufgaben in Aufgabenwarteschlangen.

Pub/Sub bietet mehr Features als die Pull-Funktionalität der Aufgabenwarteschlange. Pub/Sub hat beispielsweise auch Push-Funktionen, aber Cloud Tasks ähnelt eher Push-Aufgaben aus Aufgabenwarteschlangen. Daher wird Pub/Sub-Push nicht von einem der Migrationsmodule abgedeckt. In diesem Codelab für Modul 19 wird demonstriert, wie der Warteschlangenmechanismus von Pull-Warteschlangen der Aufgabenwarteschlange zu Pub/Sub gewechselt und für den Zugriff auf Cloud Datastore von App Engine NDB zu Cloud NDB migriert wird. Dabei wird die Migration in Modul 2 wiederholt.

Während der Code von Modul 18 „beworben“ wird als Python 2-Beispielanwendung ist die Quelle selbst mit Python 2 und 3 kompatibel. Das gilt auch nach der Migration zu Cloud Pub/Sub (und Cloud NDB) hier in Modul 19.

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
  4. Neue Google Cloud-Dienste/APIs aktivieren

Mit diesen Schritten stellen Sie sicher, dass Sie mit funktionierendem Code beginnen und er für die Migration zu Cloud-Diensten bereit ist.

1. Projekt einrichten

Wenn Sie das Codelab für Modul 18 abgeschlossen haben, verwenden Sie dasselbe Projekt (und Code) wieder. Alternativ können Sie ein neues Projekt erstellen oder ein anderes vorhandenes Projekt wiederverwenden. Achten Sie darauf, dass das Projekt ein aktives Rechnungskonto und eine aktivierte App Engine-Anwendung hat. Suchen Sie Ihre Projekt-ID, da Sie sie in diesem Codelab immer zur Hand haben sollten. Verwenden Sie sie immer dann, wenn Sie auf die Variable PROJECT_ID stoßen.

2. Baseline-Beispiel-App abrufen

Eine der Voraussetzungen ist eine funktionierende App Engine-App für Modul 18. Füllen Sie entweder das Codelab aus (empfohlen; Link oben) oder kopieren Sie den Code von Modul 18 aus dem Repository. Ganz gleich, ob Sie Ihre oder unsere verwenden – hier beginnen wir („START“). Dieses Codelab führt Sie durch die Migration und enthält zum Schluss Code, der dem im Repository-Ordner von Modul 19 („FINISH“) ähnelt.

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

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

3. Referenz-App noch einmal bereitstellen und validieren

Führen Sie die folgenden Schritte aus, um die Modul 18-Anwendung 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 auf Ihrem Entwicklungscomputer sowohl Python 2 als auch Python 3 installiert sind, müssen Sie möglicherweise stattdessen pip2 verwenden.
  2. Prüfen Sie, ob das gcloud-Befehlszeilentool installiert und initialisiert und seine Nutzung geprüft wurde.
  3. (Optional) Legen Sie für Ihr Cloud-Projekt gcloud config set project PROJECT_ID fest, wenn Sie den PROJECT_ID nicht bei jedem gcloud-Befehl eingeben möchten.
  4. Beispielanwendung mit gcloud app deploy bereitstellen
  5. Prüfen Sie, ob die App wie erwartet funktioniert, ohne dass Probleme auftreten. Wenn Sie das Codelab für Modul 18 abgeschlossen haben, werden in der App die Top-Besucher zusammen mit Ihren letzten Besuchen angezeigt (siehe Abbildung unten). Andernfalls werden möglicherweise keine Besucherzahlen angezeigt.

b667551dcbab1a09.png

Bevor Sie die Beispielanwendung für Modul 18 migrieren, müssen Sie zuerst die Cloud-Dienste aktivieren, die von der geänderten Anwendung verwendet werden sollen.

4. Neue Google Cloud-Dienste/APIs aktivieren

In der alten Anwendung wurden gebündelte App Engine-Dienste verwendet, die keine zusätzliche Einrichtung erfordern, aber eigenständige Cloud-Dienste bereits. Die aktualisierte Anwendung verwendet sowohl Cloud Pub/Sub als auch Cloud Datastore (über die Cloud NDB-Clientbibliothek). App Engine und beide Cloud APIs bieten "Immer kostenlos"- Stufen berechnet. Solange Sie unter diesen Limits bleiben, sollten Ihnen durch das Ausführen dieser Anleitung keine Kosten entstehen. Cloud APIs können je nach Bedarf entweder über die Cloud Console oder über die Befehlszeile aktiviert werden.

Über die Cloud Console

Rufen Sie in der Cloud Console die Seite API Manager-Bibliothek (für das richtige Projekt) auf und suchen Sie über die Suchleiste in der Mitte der Seite nach der Cloud Datastore API und der Cloud Pub/Sub API:

c7a740304e9d35b.png

Klicken Sie für jede API einzeln auf die Schaltfläche Aktivieren. Dann werden Sie möglicherweise aufgefordert, Zahlungsinformationen anzugeben. Dies ist beispielsweise die Seite der Cloud Pub/Sub API-Bibliothek:

1b6c0a2a73124f6b.jpeg

Über die Befehlszeile

Dies ist zwar visuell informativ, wenn APIs über die Konsole aktiviert werden, aber einige 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 einzugeben. Wenn Sie andere Cloud APIs aktivieren und deren URIs kennen möchten, finden Sie diese unten auf der Bibliotheksseite jeder API. Achten Sie beispielsweise auf pubsub.googleapis.com als „Dienstname“ unten auf der Pub/Sub-Seite direkt darüber.

Nach Abschluss der Schritte kann Ihr Projekt auf die APIs zugreifen. Jetzt ist es an der Zeit, die Anwendung so zu aktualisieren, dass diese APIs verwendet werden.

4. Pub/Sub-Ressourcen erstellen

Zusammenfassung der Sequenzreihenfolge des Workflows für Aufgabenwarteschlangen aus Modul 18:

  1. In Modul 18 wurde die Datei queue.yaml verwendet, um eine Pull-Warteschlange mit dem Namen pullq zu erstellen.
  2. Die App fügt der Pull-Warteschlange Aufgaben hinzu, um Besucher nachzuverfolgen.
  3. Aufgaben werden schließlich von einem Worker verarbeitet, der für einen begrenzten Zeitraum (eine Stunde) gemietet wird.
  4. Aufgaben werden ausgeführt, um die Anzahl der letzten Besucher zu ermitteln.
  5. Aufgaben werden nach Abschluss aus der Warteschlange gelöscht.

Sie replizieren einen ähnlichen Workflow mit Pub/Sub. Im nächsten Abschnitt wird die grundlegende Pub/Sub-Terminologie vorgestellt. Es gibt drei verschiedene Möglichkeiten, die erforderlichen Pub/Sub-Ressourcen zu erstellen.

App Engine-Aufgabenwarteschlange (Pull) im Vergleich zur Cloud Pub/Sub-Terminologie

Der Wechsel zu Pub/Sub erfordert eine geringfügige Anpassung deines Vokabulars. Nachfolgend sind die Hauptkategorien und relevante Begriffe aus beiden Produkten aufgeführt. Im Migrationsleitfaden finden Sie ähnliche Vergleiche.

  • Datenstruktur in der Warteschlange:Bei der Aufgabenwarteschlange werden die Daten in Pull-Warteschlangen eingereiht. Bei Verwendung von Pub/Sub werden Daten Themen zugeordnet.
  • Einheiten für Daten in der Warteschlange : Pull-Aufgaben mit Aufgabenwarteschlange werden bei Pub/Sub als Nachrichten bezeichnet.
  • Datenverarbeiter: Über die Aufgabenwarteschlange greifen Worker auf Pull-Aufgaben zu. mit Pub/Sub benötigen Sie Abos/Abonnenten, um Nachrichten zu empfangen
  • Datenextraktion : Das Leasing einer Pull-Aufgabe entspricht dem Abrufen einer Nachricht aus einem Thema (über ein Abo).
  • Bereinigung/Vervollständigung : Das Löschen einer Aufgabe in der Aufgabenwarteschlange aus einer Pull-Warteschlange nach dem Abschluss erfolgt analog zum Bestätigen einer Pub/Sub-Nachricht.

Obwohl sich das Warteschlangenprodukt ändert, ist der Workflow relativ ähnlich:

  1. Anstelle einer Pull-Warteschlange verwendet die Anwendung ein Thema mit dem Namen pullq.
  2. Anstatt einer Pull-Warteschlange Aufgaben hinzuzufügen, sendet die App Nachrichten an ein Thema (pullq).
  3. Anstatt Aufgaben aus der Pull-Warteschlange freizugeben, ruft ein Abonnent namens worker Nachrichten aus dem Thema pullq ab.
  4. Die Anwendung verarbeitet Nachrichtennutzlasten und erhöht die Anzahl der Besucher im Datenspeicher.
  5. Statt Aufgaben aus der Pull-Warteschlange zu löschen, bestätigt die App die verarbeiteten Nachrichten.

Bei der Aufgabenwarteschlange muss für die Einrichtung die Pull-Warteschlange erstellt werden. Mit Pub/Sub müssen für die Einrichtung sowohl ein Thema als auch ein Abo erstellt werden. In Modul 18 haben wir queue.yaml außerhalb der App-Ausführung verarbeitet. Jetzt muss das Gleiche mit Pub/Sub gemacht werden.

Es gibt drei Möglichkeiten zum Erstellen von Themen und Abos:

  1. Über die Cloud Console
  2. Über die Befehlszeile oder
  3. Aus Code (kurzes Python-Skript)

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:

  1. Rufen Sie in der Cloud Console die Seite "Pub/Sub-Themen" auf.
  2. Klicken Sie oben auf Thema erstellen. Ein neues Dialogfeld wird geöffnet (siehe Abbildung unten).
  3. Geben Sie im Feld Themen-ID den Wert pullq ein.
  4. Heben Sie die Auswahl aller ausgewählten Optionen auf und wählen Sie dann Von Google verwalteter Verschlüsselungsschlüssel aus.
  5. Klicken Sie auf die Schaltfläche Thema erstellen.

Das Dialogfeld zur Themenerstellung sieht so aus:

a05cfdbf64571ceb.png

Nachdem Sie nun ein Thema haben, muss ein Abo für dieses Thema erstellt werden:

  1. Rufen Sie in der Cloud Console die Seite Pub/Sub-Abos auf.
  2. Klicken Sie oben auf Abo erstellen (siehe Abbildung unten).
  3. Geben Sie in das Feld Abo-ID den Wert worker ein.
  4. Wählen Sie pullq aus dem Drop-down-Menü Cloud Pub/Sub-Thema auswählen aus und notieren Sie sich den "vollständig qualifizierten Pfadnamen". Beispiel: projects/PROJECT_ID/topics/pullq
  5. Wählen Sie als Zustellungstyp die Option Pull aus.
  6. Lassen Sie alle anderen Optionen unverändert und klicken Sie auf Erstellen.

So sieht der Bildschirm zur Aboerstellung aus:

c5444375c20b0618.jpeg

Sie können auch auf der Seite Themen ein Abo erstellen. kann dir dabei helfen, 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, führt dies zu der folgenden 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 auch auf dieser Seite der Kurzanleitungsdokumentation. Die Verwendung der Befehlszeile kann Workflows vereinfachen, bei denen regelmäßig Themen und Abos erstellt werden. Solche Befehle können zu diesem Zweck in Shell-Skripts verwendet werden.

Aus Code (kurzes Python-Skript)

Eine weitere Möglichkeit zum Automatisieren der Erstellung von Themen und Abos ist die Verwendung der Pub/Sub API im Quellcode. Unten sehen Sie den Code für das maker.py-Script im Repository-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 (vorausgesetzt, es sind keine Fehler):

$ python3 maker.py
Created topic 'pullq' (projects/PROJECT_ID/topics/pullq)
Subscription created 'worker' (projects/PROJECT_ID/subscriptions/worker)

Wenn die API aufgerufen wird, um bereits vorhandene Ressourcen zu erstellen, wird die Ausnahme google.api_core.exceptions.AlreadyExists ausgelöst, die von der Clientbibliothek ausgelöst und 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 Whitepaper zur Pub/Sub-Architektur weitere Informationen.

5. Konfiguration aktualisieren

Konfigurationsaktualisierungen umfassen sowohl das Ändern verschiedener Konfigurationsdateien als auch das Erstellen des Äquivalents von App Engine-Pull-Warteschlangen innerhalb der Cloud Pub/Sub-Umgebung.

queue.yaml löschen

Die Aufgabenwarteschlange wird vollständig eingestellt. Löschen Sie daher queue.yaml, da Pub/Sub diese Datei nicht verwendet. 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. Ihre aktualisierte requirements.txt in Modul 19 sollte jetzt so aussehen:

flask
google-cloud-ndb
google-cloud-pubsub

Diese requirements.txt-Datei enthält keine Versionsnummern. Es sind also die neuesten Versionen ausgewählt. Sollten Inkompatibilitäten auftreten, folgen Sie der Standardpraxis, Versionsnummern zu verwenden, um funktionierende Versionen für eine App festzulegen.

app.yaml

Die Änderungen an app.yaml unterscheiden sich, je nachdem, ob Sie bei Python 2 bleiben oder ein Upgrade auf Python 3 ausführen.

Python 2

Mit dem obigen Update für requirements.txt werden Google Cloud-Clientbibliotheken verwendet. Diese erfordern zusätzliche Unterstützung von App Engine, insbesondere einige integrierte Bibliotheken, setuptools und grpcio. Die Verwendung von integrierten Bibliotheken erfordert einen libraries-Abschnitt in app.yaml und Bibliotheksversionsnummern oder „latest“ finden Sie die neuesten Informationen zu App Engine-Servern. app.yaml in Modul 18 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 neuesten Versionen aus. Fügen Sie außerdem einen Platzhaltereintrag vom Typ runtime für Python 3 hinzu, der zusammen mit einem aktuellen 3.x-Release (z. B. 3.10) zum Zeitpunkt dieses Artikels auskommentiert wurde. Mit diesen Änderungen sieht app.yaml jetzt so aus:

NACHHER:

#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 sowie die Anweisungen threadsafe und api_version und erstellen keinen libraries-Abschnitt.

Laufzeiten der zweiten Generation bieten keine integrierten Bibliotheken von Drittanbietern, sodass der Abschnitt libraries in app.yaml nicht erforderlich ist. Außerdem ist das Kopieren (manchmal als Vendoring oder Selbstbündelung) von nicht integrierten Drittanbieterpaketen nicht mehr erforderlich. Sie müssen nur die Drittanbieterbibliotheken auflisten, die Ihre App in requirements.txt verwendet.

Im Abschnitt handlers in app.yaml werden Handler für Anwendungen (Script) und statische Dateien angegeben. Da für die Python 3-Laufzeit Web-Frameworks zum Ausführen ihres eigenen Routings erforderlich sind, müssen alle Skript-Handler in auto geändert werden. Wenn Ihre Anwendung (wie in Modul 18) keine statischen Dateien bereitstellt, wären alle Routen auto und damit irrelevant. Der Abschnitt handlers wird deshalb auch nicht benötigt. Löschen Sie ihn daher.

In Python 3 werden weder die threadsafe- noch die api_version-Anweisung verwendet. Löschen Sie diese ebenfalls. Das Fazit ist, dass Sie alle Abschnitte von app.yaml löschen sollten, damit nur die runtime-Anweisung vorhanden ist und eine aktuelle Version von Python 3 angegeben wird, z. B. 3.10. So sieht app.yaml vor und nach diesen Updates aus:

VORHER:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

NACHHER:

runtime: python310

Für alle, die noch nicht alles aus ihrem app.yaml für Python 3 löschen möchten, haben wir im Repository-Ordner des Moduls 19 eine alternative Datei mit app3.yaml zur Verfügung gestellt. Wenn Sie dies stattdessen für Bereitstellungen verwenden möchten, müssen Sie diesen Dateinamen an das Ende des Befehls anhängen: gcloud app deploy app3.yaml. Andernfalls wird standardmäßig Ihre App mit der Python 2-Datei app.yaml bereitgestellt, die Sie unverändert gelassen haben.

appengine_config.py

Wenn Sie ein Upgrade auf Python 3 ausführen, ist appengine_config.py nicht erforderlich. Löschen Sie es daher. Die Unterstützung von Drittanbieterbibliotheken ist daher nicht erforderlich, weil sie nur in requirements.txt angegeben werden müssen. Python 2-Nutzer: Lesen Sie weiter.

appengine_config.py in Modul 18 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 soeben hinzugefügten integrierten Bibliotheken (setuptools, grpcio) zu unterstützen. Es sind noch einige Zeilen erforderlich. Aktualisieren Sie appengine_config.py daher so:

NACHHER:

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 Änderungen, die zur Unterstützung von Cloud-Clientbibliotheken erforderlich sind, finden Sie in der Dokumentation zum Migrieren gebündelter Dienste.

Weitere Konfigurationsaktualisierungen

Wenn Sie einen lib-Ordner haben, löschen Sie ihn. Wenn Sie Python 2-Nutzer sind, füllen Sie den Ordner lib mit dem folgenden Befehl auf:

pip install -t lib -r requirements.txt  # or pip2

Wenn Sie sowohl Python 2 als auch 3 auf Ihrem Entwicklungssystem installiert haben, müssen Sie möglicherweise pip2 anstelle von pip verwenden.

6. Anwendungscode ändern

Dieser Abschnitt enthält Aktualisierungen der Hauptanwendungsdatei main.py, wodurch die Verwendung von Pull-Warteschlangen der App Engine-Aufgabenwarteschlange durch Cloud Pub/Sub ersetzt wird. An der Webvorlage templates/index.html wurden keine Änderungen vorgenommen. Beide Apps sollten auf die gleiche Weise funktionieren und dieselben Daten anzeigen.

Importe und Initialisierung aktualisieren

Bei den Importen und der Initialisierung wurden mehrere Aktualisierungen vorgenommen:

  1. Ersetzen Sie für die Importe App Engine NDB und Task Queue durch Cloud NDB und Pub/Sub.
  2. Benennen Sie pullq von einem QUEUE-Namen in einen TOPIC-Namen um.
  3. Bei Pull-Aufgaben wurden sie vom Worker für eine Stunde freigegeben. Mit Pub/Sub werden Zeitüberschreitungen jedoch pro Nachricht gemessen. Löschen Sie daher die Konstante HOUR.
  4. Für Cloud APIs ist die Verwendung eines API-Clients erforderlich. Initiieren Sie deshalb diejenigen für Cloud NDB und Cloud Pub/Sub, wobei Letzterer Clients für Themen und Abos bereitstellt.
  5. Pub/Sub benötigt die Cloud-Projekt-ID. Daher müssen Sie sie importieren und von google.auth.default() abrufen.
  6. Pub/Sub erfordert „vollständig qualifizierte Pfadnamen“ für Themen und Abos. Diese erstellen Sie also mit den Komfortfunktionen von *_path().

Im Folgenden sehen Sie die Importe und Initialisierungen aus Modul 18, gefolgt von den Abschnitten, die nach der Implementierung der obigen Änderungen aussehen sollten, wobei der Großteil des neuen Codes aus verschiedenen Pub/Sub-Ressourcen besteht:

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__)

NACHHER:

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)

Aktualisierungen des Datenmodells aufrufen

Das Visit-Datenmodell ändert sich nicht. Für den Datastore-Zugriff ist die explizite Verwendung des Cloud NDB API-Clientkontextmanagers ds_client.context() erforderlich. In Code bedeutet dies, dass Datastore-Aufrufe sowohl in store_visit() als auch in fetch_visits() in Python-with-Blöcken umschlossen werden. Dieses Update ist identisch mit dem, was in Modul 2 behandelt wird.

Die wichtigste Änderung für Pub/Sub besteht darin, die Einreihung einer Aufgabenwarteschlangen-Pull-Aufgabe durch die Veröffentlichung einer Pub/Sub-Nachricht im Thema pullq zu ersetzen. Unten sehen Sie den Code vor und nach diesen Aktualisierungen:

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)

NACHHER:

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 VisitorCount-Datenmodells

Das Datenmodell VisitorCount ändert sich nicht und führt fetch_counts() aus, außer dass seine Datastore-Abfrage wie unten dargestellt in einen with-Block eingebunden wird:

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)

NACHHER:

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, sodass NDB durch Cloud NDB und Aufgabenwarteschlange durch Pub/Sub ersetzt wird, der Workflow bleibt jedoch derselbe.

  1. Binden Sie Datastore-Aufrufe in den Block with des Cloud NDB-Kontextmanagers ein.
  2. Bei der Bereinigung der Aufgabenwarteschlange werden alle Aufgaben aus der Pull-Warteschlange gelöscht. Mit Pub/Sub: „Bestätigungs-IDs“ werden in acks erfasst und am Ende gelöscht/bestätigt.
  3. Pull-Aufgaben der Aufgabenwarteschlange werden auf ähnliche Weise wie Pub/Sub-Nachrichten geleast. Während das Löschen von Pull-Aufgaben mit den Aufgabenobjekten selbst erfolgt, werden Pub/Sub-Nachrichten über ihre Bestätigungs-IDs gelöscht.
  4. Für Pub/Sub-Nachrichtennutzlasten sind Byte (keine Python-Strings) erforderlich. Daher ist eine gewisse UTF-8-Codierung und -Decodierung erforderlich, wenn Nachrichten in einem Thema veröffentlicht und daraus abgerufen werden.

Ersetzen Sie log_visitors() durch den aktualisierten Code unten, der die gerade beschriebenen Änderungen implementiert:

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))

NACHHER:

@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() wurden keine Änderungen vorgenommen. Auch an der HTML-Vorlagendatei templates/index.html sind keine Änderungen erforderlich. Damit sind alle erforderlichen Aktualisierungen abgeschlossen. Herzlichen Glückwunsch zu Ihrer neuen Modul 19-Anwendung mit Cloud Pub/Sub!

7. Zusammenfassung/Bereinigung

Stellen Sie Ihre Anwendung bereit, um zu prüfen, ob sie wie vorgesehen und in jeder ausgegebenen Ausgabe funktioniert. Führen Sie auch den Worker aus, um die Besucherzahlen zu verarbeiten. Führen Sie nach der App-Überprüfung alle Bereinigungsschritte durch und erwägen Sie die nächsten Schritte.

Anwendung bereitstellen und prüfen

Prüfen Sie, ob Sie das Thema pullq und das worker-Abo bereits erstellt haben. Wenn dies abgeschlossen ist und die Beispielanwendung einsatzbereit ist, stellen Sie die Anwendung mit gcloud app deploy bereit. Die Ausgabe sollte mit der App von Modul 18 identisch sein, mit der Ausnahme, dass Sie den gesamten zugrunde liegenden Warteschlangenmechanismus erfolgreich ersetzt haben:

b667551dcbab1a09.png

Das Web-Front-End der Anwendung überprüft nun, ob dieser Teil der Anwendung funktioniert. In diesem Teil der App werden zwar erfolgreich die Top-Besucher und die letzten Besuche abgefragt und angezeigt, die App registriert diesen Besuch jedoch zusammen mit der Erstellung einer Pull-Aufgabe, mit der dieser Besucher zur Gesamtzahl hinzugefügt wird. Diese Aufgabe befindet sich nun in der Warteschlange und wartet auf ihre Verarbeitung.

Sie können dies mit einem App Engine-Back-End-Dienst, einem cron-Job, dem Aufrufen von /log oder dem Senden einer HTTP-Befehlszeilenanfrage ausführen. Hier sehen Sie ein Beispiel für die Ausführung und den Aufruf des Worker-Codes durch curl (ersetzen Sie PROJECT_ID):

$ curl https://PROJECT_ID.appspot.com/log
DONE (with 1 task[s] logging 1 visitor[s])

Die aktualisierte Anzahl wird dann beim nächsten Website-Besuch berücksichtigt. Fertig!

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:

  • Verschiedene Komponenten von Cloud Pub/Sub haben eine kostenlose Stufe. ermitteln Sie Ihre Gesamtnutzung, um sich ein besseres Bild von den Auswirkungen auf die Kosten zu machen. Weitere Einzelheiten finden Sie in der Preisübersicht.
  • Der App Engine Datastore-Dienst wird von Cloud Datastore (Cloud Firestore im Datastore-Modus) bereitgestellt, der ebenfalls eine kostenlose Stufe hat. Weitere Informationen finden Sie auf der Preisseite.

Nächste Schritte

Abgesehen von dieser Anleitung gibt es weitere Migrationsmodule, die sich auf die Umstellung von den gebündelten Legacy-Diensten konzentrieren:

  • Modul 2: von App Engine ndb zu Cloud NDB migrieren
  • Module 7–9: Migration von App Engine-Aufgabenwarteschlange (Push-Aufgaben) zu Cloud Tasks
  • Module 12–13: Migration von App Engine Memcache zu Cloud Memorystore
  • 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 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 Workflows für die Anwendungsentwicklung geworden ist, insbesondere wenn sie aus einer CI/CD-Pipeline (Continuous Integration/Continuous Delivery oder Bereitstellung) besteht, sollten Sie eine Migration zu Cloud Run in Betracht ziehen. Diese Szenarien werden in den folgenden Modulen behandelt:

  • Migration von App Engine zu Cloud Functions: siehe Modul 11
  • Migration von App Engine zu Cloud Run: Siehe Modul 4 zum Containerisieren Ihrer Anwendung mit Docker oder Modul 5 zur Implementierung von Containern, Docker-Kenntnissen oder Dockerfile

Der Wechsel zu einer anderen serverlosen Plattform ist optional. Wir empfehlen Ihnen, die besten Optionen für Ihre Anwendungen und Anwendungsfälle zu erwägen, bevor Sie Änderungen vornehmen.

Unabhängig davon, welches Migrationsmodul Sie als Nächstes in Betracht ziehen, können Sie auf alle Inhalte der Serverless Migration Station (Codelabs, Videos, Quellcode [falls verfügbar]) über das Open-Source-Repository zugreifen. Im README des Repositorys finden Sie außerdem Informationen dazu, welche Migrationen berücksichtigt werden müssen und welche relevante „Reihenfolge“ Sie haben Migrationsmodule.

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.

Probleme/Feedback mit Codelabs

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

In der folgenden Tabelle finden Sie Links zu den Repository-Ordnern für Modul 18 (START) und Modul 19 (FINISH).

Codelab

Python 2

Python 3

Modul 18

code

(nicht zutreffend)

Modul 19 (dieses Codelab)

code

(entspricht Python 2, außer verwenden Sie app3.yaml, es sei denn, Sie haben app.yaml wie oben beschrieben aktualisiert)

Onlinereferenzen

Im Folgenden finden Sie Ressourcen, die für diese Anleitung relevant sind:

App Engine-Aufgabenwarteschlange

Cloud Pub/Sub

App Engine NDB und Cloud NDB (Datenspeicher)

App Engine-Plattform

Weitere Cloud-Informationen

Videos

Lizenz

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