Modul 6: Von Cloud Datastore zu Cloud Firestore migrieren

1. Übersicht

Diese Reihe von Codelabs (Tutorials zum selbstbestimmten Lernen) soll Google App Engine-Entwicklern (Standard) helfen, ihre Apps zu modernisieren, indem sie durch eine Reihe von Migrationen geführt werden. Bei den meisten dieser Migrationen werden die gebündelten Dienste der ursprünglichen Laufzeit nicht mehr verwendet, da die Laufzeiten der nächsten Generation flexibler sind und Nutzern eine größere Auswahl an Diensten bieten. Eine weitere Möglichkeit zur Modernisierung einer App besteht darin, auf ein neueres Produkt umzusteigen. Das ist das Thema dieses Codelabs.

App Engine-Nutzer, die mit den Clientbibliotheken Cloud NDB oder Cloud Datastore auf Datastore zugreifen, müssen keine weiteren Migrationen durchführen. Cloud Firestore ist jedoch der neueste, skalierbare, hochverfügbare NoSQL-Datenspeicher mit Funktionen aus der Firebase Realtime Database.

Sie sind hier richtig, wenn Sie als Entwickler Firestore nutzen möchten, um die Vorteile der Funktionen zu nutzen, oder zumindest genug Interesse haben, um zu erfahren, was die Migration beinhaltet. In dieser Anleitung erfahren Sie, wie Sie eine App Engine-Anwendung, die Cloud Datastore verwendet, zu Cloud Firestore migrieren.

In diesem Kurs lernen Sie, wie Sie

  • Unterschiede zwischen Datastore und Firestore erkennen
  • Von Cloud Datastore zu Cloud Firestore migrieren

Voraussetzungen

Umfrage

Wie werden Sie dieses Codelab verwenden?

Nur lesen Lesen und Übungen machen

2. Hintergrund

Der Datastore von App Engine wurde 2013 zu einem eigenen Produkt, Google Cloud Datastore, und ist jetzt für Entwickler außerhalb von App Engine verfügbar. Im folgenden Jahr wurde Firebase von Google übernommen. Damals war es für seine Echtzeitdatenbank bekannt.

In den folgenden Jahren arbeiteten die Firebase- und Cloud Datastore-Teams daran, einige der Firebase-Funktionen in Datastore zu integrieren. Daher wurde 2017 die nächste Generation von Cloud Datastore veröffentlicht. Um die Übernahme einiger Firebase-Funktionen widerzuspiegeln, wurde es in Cloud Firestore umbenannt.

Cloud Firestore wurde zum standardmäßigen NoSQL-Speichermechanismus für Google Cloud-Projekte. Neue Apps können Cloud Firestore nativ verwenden, während vorhandene Datastore-Datenbanken im Hintergrund in Firestore konvertiert wurden und jetzt als „Firestore im Datastore-Modus“ ausgeführt werden, um die Kompatibilität mit Datastore-Vorgängen zu gewährleisten. Daher können Anwendungen Cloud Firestore nur in einem dieser Modi verwenden. Der Modus kann nach dem Festlegen nicht mehr geändert werden.

Wenn Nutzer derzeit neue Projekte erstellen und eine NoSQL-Lösung auswählen, werden sie aufgefordert, entweder Firestore im Datastore-Modus oder Firestore im nativen Modus auszuwählen. Sobald Nutzer Datastore-Entitäten hinzufügen, können sie nicht mehr zu Firestore wechseln. Wenn der native Modus von Firestore ausgewählt ist, können sie nicht mehr zu Datastore (bzw. Firestore im Datastore-Modus) zurückkehren. Weitere Informationen finden Sie in der Dokumentation auf der Seite Zwischen Cloud Firestore im Datastore-Modus und nativem Firestore-Modus wählen. Um eine App zu Firestore zu migrieren, muss ein neues Projekt erstellt, Datastore exportiert und dann in Firestore importiert werden. In dieser Anleitung sollen Entwickler einen Eindruck von den Unterschieden zwischen Cloud Datastore und Cloud Firestore erhalten.

Diese Migration muss nicht von Nutzern durchgeführt werden. Daher ist sie optional. Die native Verwendung von Cloud Firestore bietet zwar offensichtliche Vorteile wie die Clientauthentifizierung, die Integration von Firebase-Regeln und natürlich die Firebase Realtime Database, die Migrationsschritte sind jedoch umständlich:

  • Sie müssen ein anderes Projekt als das Projekt Ihrer aktuellen App verwenden.
  • Ein Projekt, in dem einer App Datastore-Entitäten hinzugefügt wurden, kann nicht auf Firestore im nativen Modus umgestellt werden.
  • Ebenso kann ein Projekt, für das Firestore im nativen Modus ausgewählt wurde, nicht zu Firestore im Datastore-Modus zurückkehren.
  • Es gibt kein Migrationstool, mit dem Daten von einem Projekt in ein anderes gestreamt werden können.
  • Einige wichtige Datastore-Funktionen, darunter Namespaces und ein höherer Schreibdurchsatz (> 10.000 Schreibvorgänge pro Sekunde), sind in Firestore nicht verfügbar.
  • Die Export- und Importtools sind „primitiv“ und „Alles-oder-Nichts“-Szenarien.
    • Wenn Ihre App viele Datastore-Entitäten hat, kann es viele Stunden dauern, sie zu exportieren und dann in Firestore zu importieren.
    • Während dieser Zeit kann Ihre Anwendung/Ihr Dienst keine Daten schreiben oder aktualisieren.
    • Migrationsaktivitäten werden auf die normale Nutzung angerechnet. Um Kosten zu minimieren, sollten Sie die Migration nach Möglichkeit auf tägliche Kontingente verteilen.
    • Da Ihr neuer Dienst in einem anderen Projekt ausgeführt wird, benötigen Sie Zeit, bis die DNS-Aktualisierungen übernommen werden.
  • Datastore und Firestore haben ähnliche, aber unterschiedliche Datenmodelle. Für die Migration muss daher die Funktionsweise der App/des Dienstes aktualisiert werden.
    • Ancestor-Abfragen aus Datastore sind jetzt Firestore-Sammlungsabfragen (Standard).
    • Breite Typabfragen aus Datastore sind Firestore-Sammlungsgruppenabfragen.
    • Die Indexierung und Verarbeitung sind unterschiedlich.

Wenn Sie eine relativ einfache App haben, die Sie migrieren möchten, sich auf die Simulation einer solchen Migration vorbereiten oder einfach nur mehr über Datastore und Firestore erfahren möchten, lesen Sie bitte weiter.

Python 2-Nutzer:Dieses optionale Codelab zur Migration wird nur in Python 3 präsentiert. Da Cloud Firestore jedoch auch 2.x unterstützt, können Nutzer die Unterschiede in der Verwendung interpolieren. Ein Beispiel: Firestore-Datensätze verwenden Unicode-Strings (anstatt Byte-Strings). Daher ist für Python 2-Stringliterale ein u''-Indikator erforderlich. Eine store_visit()-Funktion in Version 2.x sieht so aus:

def store_visit(remote_addr, user_agent):
    doc_ref = fs_client.collection(u'Visit')
    doc_ref.add({
        u'timestamp': datetime.now(),
        u'visitor': u'{}: {}'.format(remote_addr, user_agent),
    })

Ansonsten sollte die Clientbibliothek ähnlich funktionieren. Das einzige andere Problem, das berücksichtigt werden muss, ist, dass die Cloud Firestore-Bibliothek 2.x in Bezug auf die Entwicklung „eingefroren“ ist. Immer mehr/neuere Funktionen sind also nur in der Firestore-Clientbibliothek 3.x verfügbar.

Die wichtigsten Schritte dieser Anleitung sind:

  1. Einrichtung/Vorbereitung
  2. Cloud Firestore-Bibliothek hinzufügen
  3. Anwendungsdateien aktualisieren

3. Einrichtung/Vorbereitung

Bevor wir mit dem Hauptteil des Tutorials beginnen, richten wir unser Projekt ein, rufen den Code ab und stellen die Baseline-App bereit, damit wir wissen, dass wir mit funktionierendem Code begonnen haben.

1. Projekt einrichten

Wir empfehlen, dass Sie dasselbe Projekt wie für das Codelab zu Modul 3 verwenden. Alternativ können Sie ein neues Projekt erstellen oder ein anderes vorhandenes Projekt wiederverwenden. Prüfen Sie, ob das Projekt ein aktives Abrechnungskonto hat und App Engine (App) aktiviert ist.

2. Beispiel-App für die Baseline abrufen

Eine der Voraussetzungen für dieses Codelab ist eine funktionierende Beispiel-App aus Modul 3. Wenn Sie keine haben, arbeiten Sie zuerst das Tutorial zu Modul 3 (Link oben) durch, bevor Sie hier fortfahren. Wenn Sie bereits mit den Inhalten vertraut sind, können Sie direkt mit dem Code aus Modul 3 unten beginnen.

Unabhängig davon, ob Sie Ihren oder unseren Code verwenden, ist der Code aus Modul 3 der Ausgangspunkt. In diesem Codelab zu Modul 6 werden Sie durch jeden Schritt geführt. Am Ende sollte der Code dem Code am ENDE entsprechen. Diese Anleitung ist nur für Python 3 verfügbar.

Das Verzeichnis der Dateien für Modul 3 (Ihre oder unsere) sollte so aussehen:

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

3. App für Modul 3 (erneut) bereitstellen

Das sind die verbleibenden Schritte, die Sie jetzt ausführen müssen:

  1. Machen Sie sich (falls erforderlich) noch einmal mit dem gcloud-Befehlszeilentool vertraut.
  2. Stellen Sie den Code aus Modul 3 in App Engine bereit (falls erforderlich).

Sobald Sie diese Schritte ausgeführt und bestätigt haben, dass die Appliance betriebsbereit ist, fahren wir mit dieser Anleitung fort und beginnen mit den Konfigurationsdateien.

Python 2-Anforderungen

  • Prüfen Sie, ob app.yaml (immer noch) auf die gebündelten Drittanbieterpakete grpcio und setuptools verweist.
  • Achten Sie darauf, dass appengine_config.py weiterhin pkg_resources und google.appengine.ext.vendor verwendet, um die App auf Drittanbieterressourcen zu verweisen.
  • Im nächsten Abschnitt zum Aktualisieren von requirements.txt müssen Sie google-cloud-firestore==1.9.0 verwenden, da dies die letzte mit 2.x kompatible Version der Python Firestore-Clientbibliothek ist.
    • Wenn in Ihrem requirements.txt ein Eintrag für google-cloud-core vorhanden ist, lassen Sie ihn unverändert.
    • Löschen Sie lib und installieren Sie es mit pip install -t lib -r requirements.txt neu.

4. Konfigurationsdateien aktualisieren (Cloud Firestore-Bibliothek hinzufügen)

Nach der Einrichtung müssen Sie die Konfiguration und dann die Anwendungsdateien aktualisieren. Für die erste Option ist die einzige Konfigurationsänderung ein kleiner Paketwechsel in der Datei requirements.txt. Das wollen wir jetzt vornehmen.

Ersetzen Sie die Zeile google-cloud-datastore durch google-cloud-firestore in requirements.txt, sodass sie so aussieht:

Flask==1.1.2
google-cloud-firestore==2.0.2

Wir empfehlen, die neuesten Versionen der einzelnen Bibliotheken zu verwenden. Die oben angegebenen Versionsnummern sind zum Zeitpunkt der Erstellung dieses Dokuments die aktuellen. Der Code im Ordner „FINISH“ des Repositorys wird häufiger aktualisiert und ist möglicherweise in einer neueren Version verfügbar.

Es gibt keine anderen Konfigurationsänderungen, sodass app.yaml und templates/index.html unverändert bleiben.

5. Anwendungsdateien aktualisieren

Es gibt nur eine Anwendungsdatei, main.py. Alle Änderungen in diesem Abschnitt wirken sich also nur auf diese Datei aus.

1. Importe

Das Importieren des Pakets ist eine geringfügige Änderung von datastore zu firestore:

  • VORHER:
from google.cloud import datastore
  • DANACH:
from google.cloud import firestore

2. Firestore-Zugriff

Erstellen Sie nach der Initialisierung von Flask Ihren Firestore-Client. Nehmen Sie eine ähnliche Änderung wie oben vor, aber für die Clientinitialisierung:

  • VORHER:
app = Flask(__name__)
ds_client = datastore.Client()
  • DANACH:
app = Flask(__name__)
fs_client = firestore.Client()

Durch die Migration von Cloud NDB zu Cloud Datastore haben Sie bereits die wichtigsten Schritte für die Migration zu Cloud Firestore abgeschlossen. Mit Datastore erstellen Sie Datensätze in Form von Entitäten, die aus gemeinsamen Attributen bestehen und nach Schlüsseln gruppiert werden. Datensätze in Firestore sind Dokumente, die aus Schlüssel/Wert-Paaren bestehen und in Sammlungen gruppiert sind. Wenn Sie von Datastore migrieren, müssen Sie diese Unterschiede berücksichtigen, da sie sich sowohl beim Erstellen als auch beim Abfragen von Datensätzen bemerkbar machen. Die Ergebnisse können je nach Komplexität des Datenspeicher-Codes variieren.

Für Datastore erstellen Sie Abfragen basierend auf dem Entitätstyp sowie Filter- und Sortierkriterien. Für Firestore ist das Abfragen von Daten ähnlich. Sehen wir uns ein kurzes Beispiel an, das von diesen Abfragewerten, Clients (ds_client bzw. fs_client) und Importen ausgeht:

from datetime import datetime
from firestore.Query import DESCENDING

OCT1 = datetime(2020, 10, 1)
LIMIT = 10

Für Datastore fragen wir die zehn neuesten Visit-Entitäten ab, die nach dem 1. Oktober 2020 erstellt wurden, und sortieren sie in absteigender Reihenfolge:

query = ds_client.query(kind='Visit')
query.add_filter('timestamp', '>=', datetime(2020, 10, 1))
query.order = ['-timestamp']
return query.fetch(limit=LIMIT)

Wenn Sie dasselbe für Firestore aus der Sammlung Visit tun:

query = fs_client.collection('Visit')
query.where('timestamp', '>=', datetime(2020, 10, 1))
query.order_by('timestamp', direction=DESCENDING)
return query.limit(LIMIT).stream()

Die Abfrage der Beispielanwendung ist einfacher (keine WHERE-Klausel). Hier ist der Cloud Datastore-Code:

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

def fetch_visits(limit):
    query = ds_client.query(kind='Visit')
    query.order = ['-timestamp']
    return query.fetch(limit=limit)

Bei der Migration zu Firestore ähnelt das Erstellen neuer Dokumente dem Erstellen von Entitäten und die Abfragen sind wie oben beschrieben.

  • DANACH:
def store_visit(remote_addr, user_agent):
    doc_ref = fs_client.collection('Visit')
    doc_ref.add({
        'timestamp': datetime.now(),
        'visitor': '{}: {}'.format(remote_addr, user_agent),
    })

def fetch_visits(limit):
    visits_ref = fs_client.collection('Visit')
    visits = (v.to_dict() for v in visits_ref.order_by('timestamp',
            direction=firestore.Query.DESCENDING).limit(limit).stream())
    return visits

Die Hauptfunktion root() bleibt unverändert, ebenso die Vorlagendatei index.html. Überprüfen Sie Ihre Änderungen noch einmal, speichern Sie sie, stellen Sie sie bereit und prüfen Sie sie.

6. Zusammenfassung/Bereinigung

Anwendung bereitstellen

Stellen Sie die App mit gcloud app deploy noch einmal bereit und prüfen Sie, ob sie funktioniert. Ihr Code sollte jetzt mit dem Code im Repo für Modul 6 übereinstimmen (oder mit einer Version 2.x, falls Sie diese bevorzugt haben).

Wenn Sie diese Reihe ohne die vorherigen Codelabs durchgearbeitet haben, ändert sich die App selbst nicht. Sie erfasst alle Besuche der Hauptwebseite (/) und sieht so aus, wenn Sie die Website oft genug besucht haben:

visitme app

Herzlichen Glückwunsch zum Abschluss dieser optionalen Migration von Modul 6. Dies ist wahrscheinlich eine der letzten, wenn nicht sogar die letzte Migration, die Sie in Bezug auf die Datenspeicherung in App Engine durchführen können. Eine alternative Migration, die Sie in Betracht ziehen können, ist die Containerisierung Ihrer App für Cloud Run, falls Sie dies noch nicht getan haben (siehe Modul 4 und Modul 5 der unten verlinkten Codelabs).

Optional: Bereinigen

Was ist mit der Bereinigung, um Gebühren zu vermeiden, bis Sie bereit sind, mit dem nächsten Migrations-Codelab fortzufahren? Als bestehende Entwickler sind Sie wahrscheinlich bereits mit den Preisinformationen für App Engine vertraut.

Optional: App deaktivieren

Wenn Sie noch nicht mit dem nächsten Tutorial fortfahren möchten, deaktivieren Sie Ihre App, um Kosten zu vermeiden. Wenn Sie mit dem nächsten Codelab fortfahren möchten, können Sie es wieder aktivieren. Wenn Ihre App deaktiviert ist, fallen keine Kosten für Traffic an. Allerdings können Ihnen Kosten für die Firestore-Nutzung in Rechnung gestellt werden, wenn diese das kostenlose Kontingent überschreitet. Löschen Sie daher genügend Daten, um unter diesem Limit zu bleiben.

Wenn Sie die Migrationen nicht fortsetzen und alles vollständig löschen möchten, können Sie Ihr Projekt beenden.

Nächste Schritte

Neben dieser Anleitung gibt es noch weitere Codelabs für Migrationsmodule, die Sie in Betracht ziehen können:

  • Modul 7:App Engine-Push-Aufgabenwarteschlangen (erforderlich, wenn Sie [Push-]Aufgabenwarteschlangen verwenden)
    • Fügt der App in Modul 1 taskqueue-Push-Aufgaben für App Engine hinzu
    • Bereitet Nutzer auf die Migration zu Cloud Tasks in Modul 8 vor.
  • Modul 4:Mit Docker zu Cloud Run migrieren 
    • Anwendung mit Docker für die Ausführung in Cloud Run containerisieren
    • Bei dieser Migration können Sie weiterhin Python 2 verwenden.
  • Modul 5:Mit Cloud Buildpacks zu Cloud Run migrieren 
    • Anwendung mit Cloud Buildpacks für die Ausführung in Cloud Run containerisieren
    • Sie müssen nichts über Docker, Container oder Dockerfile wissen.
    • Ihre App muss bereits zu Python 3 migriert sein (Buildpacks unterstützen Python 2 nicht).

7. Zusätzliche Ressourcen

Probleme/Feedback zu Codelabs für das App Engine-Migrationsmodul

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 3 (START) und Modul 6 (FINISH) finden Sie in der Tabelle unten. Sie können auch über das Repository für alle App Engine-Migrationen auf sie zugreifen. Sie können es klonen oder eine ZIP-Datei herunterladen.

Codelab

Python 2

Python 3

Modul 3

(Code)

code

Module 6

(n/a)

code

App Engine-Ressourcen

Unten finden Sie zusätzliche Ressourcen zu dieser speziellen Migration: