Python 2-App Engine Cloud NDB migrieren & Cloud Tasks-Anwendung für Python 3 und Cloud Datastore (Modul 9)

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.

Der Zweck dieses Codelabs besteht darin, die Beispielanwendung für Modul 8 auf Python 3 zu portieren, den Datastore-Zugriff (Cloud Firestore im Datastore-Modus) von Cloud NDB auf die native Cloud Datastore-Clientbibliothek umzustellen und ein Upgrade auf die neueste Version der Cloud Tasks-Clientbibliothek durchzuführen.

In Modul 7 haben wir die Aufgabenwarteschlange für Push-Aufgaben hinzugefügt und diese Nutzung dann in Modul 8 zu Cloud Tasks migriert. In Modul 9 geht es nun um Python 3 und Cloud Datastore. 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,

  • Beispielanwendung für Modul 8 zu Python 3 übertragen
  • Datastore-Zugriff von Cloud NDB auf Cloud Datastore-Clientbibliotheken umstellen
  • Upgrade auf die neueste Version der Cloud Tasks-Clientbibliothek durchführen

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

In Modul 7 wird gezeigt, wie Sie Push-Aufgaben für die App Engine-Aufgabenwarteschlange in Python 2 Flask App Engine-Anwendungen verwenden. In Modul 8 migrieren Sie diese Anwendung von der Aufgabenwarteschlange zu Cloud Tasks. In Modul 9 setzen Sie diesen Prozess fort. Sie portieren diese Anwendung auf Python 3 und stellen den Datastore-Zugriff von Cloud NDB auf die native Cloud Datastore-Clientbibliothek um.

Da Cloud NDB sowohl für Python 2 als auch für Python 3 funktioniert, reicht es für App Engine-Nutzer aus, die ihre Anwendungen von Python 2 nach Python 3 portieren. Eine weitere Migration von Clientbibliotheken zu Cloud Datastore ist völlig optional und es gibt nur einen Grund, dies in Betracht zu ziehen: Sie haben bereits Anwendungen, die nicht von App Engine stammen (und/oder Python 3-Anwendungen von App Engine), die die Cloud Datastore-Clientbibliothek bereits verwenden und möchten Ihre Codebasis so konsolidieren, dass der Zugriff auf Datastore mit nur einer Clientbibliothek erfolgt. Cloud NDB wurde speziell für Python 2-App Engine-Entwickler als Migrationstool für Python 3 erstellt. Wenn Sie also noch keinen Code für die Cloud Datastore-Clientbibliothek haben, müssen Sie diese Migration nicht in Betracht ziehen.

Da die Entwicklung der Cloud Tasks-Clientbibliothek nur in Python 3 fortgesetzt wird, „migrieren“ wir sie. von einer der endgültigen Python 2-Versionen bis zu Python 3. Glücklicherweise gibt es keine funktionsgefährdenden Änderungen von Python 2, sodass Sie an dieser Stelle nichts weiter tun müssen.

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 und er für die Migration zu Cloud-Diensten bereit ist.

1. Projekt einrichten

Wenn Sie das Codelab für Modul 8 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 8. Schließen Sie das Codelab für Modul 8 ab (empfohlen) oder kopieren Sie die App für Modul 8 aus dem Repository. Unabhängig davon, ob Sie Ihren oder unseren verwenden, beginnen wir mit dem Code für Modul 8 („START“). Dieses Codelab führt Sie durch die Migration und enthält zum Schluss Code, der dem im Repository-Ordner von Modul 9 ("FINISH") ähnelt.

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

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

3. Referenz-App noch einmal bereitstellen und validieren

Führen Sie die folgenden Schritte aus, um die Modul 8-App 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 8 abgeschlossen haben, werden in der App die Top-Besucher zusammen mit den letzten Besuchen angezeigt (siehe Abbildung unten). Unten sind die älteren Aufgaben zu sehen, die gelöscht werden.

4aa8a2cb5f527079.png

4. Konfiguration aktualisieren

requirements.txt

Der neue requirements.txt ist fast derselbe wie der für Modul 8, mit nur einer großen Änderung: Ersetzen Sie google-cloud-ndb durch google-cloud-datastore. Ändern Sie die Datei requirements.txt folgendermaßen:

flask
google-cloud-datastore
google-cloud-tasks

Diese requirements.txt-Datei enthält keine Versionsnummern. Es sind also die neuesten Versionen ausgewählt. Bei Inkompatibilitäten ist es üblich, Versionsnummern zu verwenden, um Arbeitsversionen für eine App festzulegen.

app.yaml

Die App Engine-Laufzeit der zweiten Generation unterstützt weder integrierte Drittanbieterbibliotheken wie in 2.x noch das Kopieren nicht integrierter Bibliotheken. Die einzige Voraussetzung für Drittanbieterpakete ist, dass sie in requirements.txt aufgelistet werden. Daher kann der gesamte libraries-Abschnitt von app.yaml gelöscht werden.

Eine weitere Aktualisierung besteht darin, dass die Python 3-Laufzeit die Verwendung von Web-Frameworks erfordert, die ihr eigenes Routing erstellen. Daher müssen alle Skript-Handler in auto geändert werden. Da jedoch alle Routen in auto geändert werden müssen und keine statischen Dateien von dieser Beispielanwendung bereitgestellt werden, ist es irrelevant, ob beliebige Handler vorhanden sind. Entfernen Sie daher auch den gesamten Abschnitt handlers.

Das Einzige, was in app.yaml erforderlich ist, besteht darin, die Laufzeit auf eine unterstützte Version von Python 3, z. B. 3.10, festzulegen. Nehmen Sie diese Änderung vor, sodass die neue, abgekürzte app.yaml nur aus dieser einzelnen Zeile besteht:

runtime: python310

appengine_config.py und lib löschen

App Engine-Laufzeiten der nächsten Generation überarbeiten die Nutzung von Drittanbieterpaketen:

  • Integrierte Bibliotheken wurden von Google geprüft und auf App Engine-Servern zur Verfügung gestellt. Wahrscheinlich enthalten sie C/C++-Code, den Entwickler nicht in der Cloud bereitstellen dürfen. Diese Bibliotheken sind in den Laufzeiten der 2. Generation nicht mehr verfügbar.
  • Das Kopieren von nicht integrierten Bibliotheken (manchmal als „Vendoring“ oder „self-bundling“ bezeichnet) ist in Laufzeiten der 2. Generation nicht mehr erforderlich. Sie sollten stattdessen in requirements.txt aufgeführt werden. Dort werden sie vom Build-System zum Zeitpunkt der Bereitstellung automatisch in Ihrem Namen installiert.

Aufgrund dieser Änderungen an der Paketverwaltung durch Drittanbieter werden weder die Datei appengine_config.py noch der Ordner lib benötigt. Löschen Sie sie daher. In Laufzeiten der 2. Generation installiert App Engine automatisch Drittanbieterpakete, die in requirements.txt aufgeführt sind. Zusammenfassung:

  1. Keine selbst gebündelten oder kopierten Bibliotheken von Drittanbietern; in requirements.txt auflisten
  2. Kein pip install in einem lib-Ordner, d. h. kein lib-Ordnerzeitraum
  3. Keine Auflistung von integrierten Bibliotheken von Drittanbietern (daher kein Abschnitt libraries) in app.yaml vorhanden; in requirements.txt auflisten
  4. Wenn du keine Bibliotheken von Drittanbietern aus deiner App referenzierst, gibt es keine appengine_config.py-Datei

Die einzige Anforderung für Entwickler besteht darin, alle gewünschten Drittanbieterbibliotheken in requirements.txt aufzulisten.

5. Anwendungsdateien aktualisieren

Es gibt nur die Anwendungsdatei main.py. Daher wirken sich alle Änderungen in diesem Abschnitt nur auf diese Datei aus. Unten sehen Sie einen „Unterschied“, Darstellung der allgemeinen Änderungen, die vorgenommen werden müssen, um den vorhandenen Code in die neue App zu refaktorieren. Von Lesern wird nicht erwartet, dass sie den Code Zeile für Zeile lesen, da er lediglich einen bildlichen Überblick über die Anforderungen dieser Refaktorierung vermittelt. Sie können ihn aber auch in einem neuen Tab öffnen oder herunterladen und bei Bedarf heranzoomen.

5d043768ba7be742.png

Importe und Initialisierung aktualisieren

Im Importabschnitt in main.py für Modul 8 werden Cloud NDB und Cloud Tasks verwendet. sollte das so aussehen:

VORHER:

from datetime import datetime
import json
import logging
import time
from flask import Flask, render_template, request
import google.auth
from google.cloud import ndb, tasks

app = Flask(__name__)
ds_client = ndb.Client()
ts_client = tasks.CloudTasksClient()

Das Logging ist in Laufzeiten der zweiten Generation wie Python 3 vereinfacht und verbessert:

  • Verwenden Sie Cloud Logging, um umfassende Logging-Erfahrungen zu erhalten.
  • Senden Sie für ein einfaches Logging einfach über print() an stdout (oder stderr)
  • Das Python-Modul logging ist nicht erforderlich. Entfernen Sie es also.

Löschen Sie daher den Import von logging und tauschen Sie google.cloud.ndb gegen google.cloud.datastore aus. Ändern Sie entsprechend ds_client so, dass es auf einen Datastore-Client statt auf einen NDB-Client verweist. Nachdem Sie diese Änderungen vorgenommen haben, sieht der obere Bereich Ihrer neuen App nun so aus:

NACHHER:

from datetime import datetime
import json
import time
from flask import Flask, render_template, request
import google.auth
from google.cloud import datastore, tasks

app = Flask(__name__)
ds_client = datastore.Client()
ts_client = tasks.CloudTasksClient()

Zu Cloud Datastore migrieren

Jetzt ist es an der Zeit, die NDB-Clientbibliotheken durch Datastore zu ersetzen. Sowohl App Engine NDB als auch Cloud NDB erfordern ein Datenmodell (Klasse). für diese App ist es Visit. Die store_visit()-Funktion funktioniert genauso wie in allen anderen Migrationsmodulen: Sie registriert einen Besuch, indem sie einen neuen Visit-Datensatz erstellt und die IP-Adresse und den User-Agent des Besucherclients (Browsertyp) speichert.

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 entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

Da Cloud Datastore jedoch keine Datenmodellklasse verwendet, löschen Sie diese Klasse. Darüber hinaus erstellt Cloud Datastore beim Erstellen von Einträgen nicht automatisch einen Zeitstempel. Sie müssen dies manuell tun. Dies erfolgt mit dem datetime.now()-Aufruf.

Ohne die Datenklasse sollte der geänderte store_visit() in etwa so aussehen:

NACHHER:

def store_visit(remote_addr, user_agent):
    'create new Visit entity in Datastore'
    entity = datastore.Entity(key=ds_client.key('Visit'))
    entity.update({
        'timestamp': datetime.now(),
        'visitor': '{}: {}'.format(remote_addr, user_agent),
    })
    ds_client.put(entity)

Die Hauptfunktion ist fetch_visits(). Es führt nicht nur die ursprüngliche Abfrage für die letzten Visits aus, sondern erfasst auch den Zeitstempel des letzten angezeigten Visit und erstellt die Push-Aufgabe, die /trim (also trim()) aufruft, um die alten Visits zu löschen. Hier wird Cloud NDB verwendet:

VORHER:

def fetch_visits(limit):
    'get most recent visits & add task to delete older visits'
    with ds_client.context():
        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)
    task = {
        'app_engine_http_request': {
            'relative_uri': '/trim',
            'body': json.dumps({'oldest': oldest}).encode(),
            'headers': {
                'Content-Type': 'application/json',
            },
        }
    }
    ts_client.create_task(parent=QUEUE_PATH, task=task)
    return (v.to_dict() for v in data), oldest_str

Die wichtigsten Änderungen:

  1. Ersetzen Sie die Cloud NDB-Abfrage durch das Cloud Datastore-Äquivalent. unterscheiden sich geringfügig.
  2. Datastore erfordert keinen Kontextmanager und lässt Sie die Daten nicht extrahieren (mit to_dict()), wie es bei Cloud NDB der Fall ist.
  3. Logging-Aufrufe durch print() ersetzen

Nach diesen Änderungen sieht fetch_visits() so aus:

NACHHER:

def fetch_visits(limit):
    'get most recent visits & add task to delete older visits'
    query = ds_client.query(kind='Visit')
    query.order = ['-timestamp']
    visits = list(query.fetch(limit=limit))
    oldest = time.mktime(visits[-1]['timestamp'].timetuple())
    oldest_str = time.ctime(oldest)
    print('Delete entities older than %s' % oldest_str)
    task = {
        'app_engine_http_request': {
            'relative_uri': '/trim',
            'body': json.dumps({'oldest': oldest}).encode(),
            'headers': {
                'Content-Type': 'application/json',
            },
        }
    }
    ts_client.create_task(parent=QUEUE_PATH, task=task)
    return visits, oldest_str

Das wäre normalerweise alles, was dazu notwendig wäre. Leider gibt es ein großes Problem.

(Möglich) Neue Push-Warteschlange erstellen

In Modul 7 haben wir der bestehenden Anwendung in Modul 1 die Verwendung von App Engine taskqueue hinzugefügt. Ein wesentlicher Vorteil von Push-Aufgaben als alte App Engine-Funktion besteht darin, wird automatisch erstellt. Als diese Anwendung in Modul 8 zu Cloud Tasks migriert wurde, war diese Standardwarteschlange bereits vorhanden. Wir mussten uns also noch keine Gedanken darüber machen. Das ändert sich in Modul 9.

Ein wichtiger Aspekt, der berücksichtigt werden muss, ist, dass die neue App Engine-Anwendung keine App Engine-Dienste mehr verwendet. Daher können Sie nicht mehr davon ausgehen, dass App Engine automatisch eine Aufgabenwarteschlange in einem anderen Produkt (Cloud Tasks) erstellt. Wie beschrieben schlägt das Erstellen einer Aufgabe in fetch_visits() (für eine nicht vorhandene Warteschlange) fehl. Eine neue Funktion ist erforderlich, um zu überprüfen, ob die Warteschlange ("Standard") vorhanden ist. Falls nicht, wird eine erstellt.

Rufen Sie die Funktion _create_queue_if() auf und fügen Sie sie Ihrer Anwendung etwas über fetch_visits() hinzu, da sie dort aufgerufen wird. Der Hauptteil der hinzuzufügenden Funktion:

def _create_queue_if():
    'app-internal function creating default queue if it does not exist'
    try:
        ts_client.get_queue(name=QUEUE_PATH)
    except Exception as e:
        if 'does not exist' in str(e):
            ts_client.create_queue(parent=PATH_PREFIX,
                    queue={'name': QUEUE_PATH})
    return True

Für die create_queue()-Funktion von Cloud Tasks ist der vollständige Pfadname der Warteschlange mit Ausnahme des Warteschlangennamens erforderlich. Erstellen Sie der Einfachheit halber eine weitere Variable PATH_PREFIX, die das QUEUE_PATH abzüglich des Warteschlangennamens (QUEUE_PATH.rsplit('/', 2)[0]) darstellt. Fügen Sie seine Definition oben hinzu, sodass der Codeblock mit allen konstanten Zuweisungen wie folgt aussieht:

_, PROJECT_ID = google.auth.default()
REGION_ID = 'REGION_ID'    # replace w/your own
QUEUE_NAME = 'default'     # replace w/your own
QUEUE_PATH = ts_client.queue_path(PROJECT_ID, REGION_ID, QUEUE_NAME)
PATH_PREFIX = QUEUE_PATH.rsplit('/', 2)[0]

Ändern Sie nun die letzte Zeile in fetch_visits(), um _create_queue_if() zu verwenden. Erstellen Sie zuerst bei Bedarf die Warteschlange und dann erstellen Sie die Aufgabe anschließend:

    if _create_queue_if():
        ts_client.create_task(parent=QUEUE_PATH, task=task)
    return visits, oldest_str

_create_queue_if() und fetch_visits() sollten nun insgesamt so aussehen:

def _create_queue_if():
    'app-internal function creating default queue if it does not exist'
    try:
        ts_client.get_queue(name=QUEUE_PATH)
    except Exception as e:
        if 'does not exist' in str(e):
            ts_client.create_queue(parent=PATH_PREFIX,
                    queue={'name': QUEUE_PATH})
    return True

def fetch_visits(limit):
    'get most recent visits & add task to delete older visits'
    query = ds_client.query(kind='Visit')
    query.order = ['-timestamp']
    visits = list(query.fetch(limit=limit))
    oldest = time.mktime(visits[-1]['timestamp'].timetuple())
    oldest_str = time.ctime(oldest)
    print('Delete entities older than %s' % oldest_str)
    task = {
        'app_engine_http_request': {
            'relative_uri': '/trim',
            'body': json.dumps({'oldest': oldest}).encode(),
            'headers': {
                'Content-Type': 'application/json',
            },
        }
    }
    if _create_queue_if():
        ts_client.create_task(parent=QUEUE_PATH, task=task)
    return visits, oldest_str

Abgesehen davon, dass Sie diesen zusätzlichen Code hinzufügen müssen, ist der Rest des Cloud Tasks-Codes größtenteils aus Modul 8 intakt. Der letzte Code-Abschnitt, den Sie sich ansehen müssen, ist der Aufgaben-Handler.

Push-Aufgaben-Handler aktualisieren

Im Aufgaben-Handler trim() fragt der Cloud NDB-Code Besuche ab, die älter als die ältesten angezeigten Besuche sind. Es wird eine ausschließlich schlüsselbasierte Abfrage verwendet, um den Vorgang zu beschleunigen – warum sollten Sie alle Daten abrufen, wenn Sie nur die Besuchs-IDs benötigen? Wenn Sie alle Besuchs-IDs haben, löschen Sie sie alle in einem Batch mit der Funktion delete_multi() von Cloud NDB.

VORHER:

@app.route('/trim', methods=['POST'])
def trim():
    '(push) task queue handler to delete oldest visits'
    oldest = float(request.get_json().get('oldest'))
    with ds_client.context():
        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

Wie bei fetch_visits() besteht der Großteil der Änderungen darin, Cloud NDB-Code für Cloud Datastore auszutauschen, die Abfragestile zu optimieren, den Kontextmanager nicht mehr zu verwenden und die Logging-Aufrufe in print() zu ändern.

NACHHER:

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

Am Hauptanwendungs-Handler root() wurden keine Änderungen vorgenommen.

Port zu Python 3

Diese Beispielanwendung wurde für die Ausführung unter Python 2 und 3 entwickelt. Alle Python 3-spezifischen Änderungen wurden zuvor in den relevanten Abschnitten dieser Anleitung behandelt. Es sind keine zusätzlichen Schritte oder Kompatibilitätsbibliotheken erforderlich.

Cloud Tasks-Update

Die endgültige Version der Cloud Tasks-Clientbibliothek, die Python 2 unterstützt, ist 1.5.0. Zum Zeitpunkt der Veröffentlichung dieses Dokuments ist die neueste Version der Clientbibliothek für Python 3 vollständig kompatibel mit dieser Version, sodass keine weiteren Aktualisierungen erforderlich sind.

Aktualisierung der HTML-Vorlage

Auch an der HTML-Vorlagendatei templates/index.html sind keine Änderungen erforderlich. Hier sind alle Änderungen zusammengefasst, die für die Modul 9-App erforderlich sind.

6. Zusammenfassung/Bereinigung

Anwendung bereitstellen und prüfen

Nachdem Sie die Codeaktualisierungen, hauptsächlich den Port für Python 3, abgeschlossen haben, stellen Sie Ihre Anwendung mit gcloud app deploy bereit. Die Ausgabe sollte mit den Anwendungen aus den Modulen 7 und 8 identisch sein. Der einzige Unterschied besteht darin, dass Sie den Datenbankzugriff auf die Cloud Datastore-Clientbibliothek verschoben und ein Upgrade auf Python 3 durchgeführt haben:

Modul 7: Visitme App

Mit diesem Schritt wird das Codelab abgeschlossen. Wir empfehlen Ihnen, Ihren Code mit dem zu vergleichen, was sich im Modul 9-Ordner befindet. Glückwunsch!

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:

  • Cloud Tasks bietet eine kostenlose Stufe. Weitere Informationen finden Sie auf der Preisseite.
  • 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

Damit ist unsere Migration von Push-Aufgaben der App Engine-Aufgabenwarteschlange zu Cloud Tasks abgeschlossen. Die optionale Migration von Cloud NDB zu Cloud Datastore wird in Modul 3 ebenfalls eigenständig (ohne Aufgabenwarteschlange oder Cloud Tasks) behandelt. Neben Modul 3 gibt es weitere Migrationsmodule, die sich darauf konzentrieren, von den gebündelten App Engine-Legacy-Diensten abzuweichen. Dazu gehören:

  • Modul 2: Von App Engine NDB zu Cloud NDB migrieren
  • Modul 3: Von Cloud NDB zu Cloud Datastore migrieren
  • Module 12–13: Migration von App Engine Memcache zu Cloud Memorystore
  • Module 15–16: Migration von App Engine Blobstore zu Cloud Storage
  • Module 18–19: App Engine-Aufgabenwarteschlange (Pull-Aufgaben) für Cloud Pub/Sub

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.

7. Zusätzliche Ressourcen

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

Links zu den Repository-Ordnern für Modul 8 (START) und Modul 9 (FINISH) finden Sie in der folgenden Tabelle. Sie können auch über das Repository für alle App Engine-Codelab-Migrationen auf sie zugreifen. Sie können eine ZIP-Datei klonen oder herunterladen.

Codelab

Python 2

Python 3

Modul 8

code

(nicht zutreffend)

Modul 9

(nicht zutreffend)

code

Online-Ressourcen

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

App Engine

Cloud NDB

Cloud Datastore

Cloud Tasks

Weitere Cloud-Informationen

Lizenz

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