1. Übersicht
Die Codelabs-Reihe zur Serverless Migration Station (zum Selbststudium, praxisorientierte Anleitungen) und ähnliche Videos sollen Entwickler von Google Cloud Serverless bei der Modernisierung ihrer Anwendungen unterstützen, indem sie eine oder mehrere Migrationen durchgehen, in erster Linie von Legacy-Diensten. Dadurch werden Ihre Anwendungen portabler und bieten mehr Optionen und Flexibilität, sodass Sie eine breitere Palette von Cloud-Produkten einbinden und darauf zugreifen sowie einfacher auf neuere Sprachversionen upgraden können. Der Schwerpunkt dieser Reihe liegt anfangs auf die ersten Cloud-Nutzer, in erster Linie auf Entwicklern von App Engine (Standardumgebung). Sie ist aber umfassend genug, um auch andere serverlose Plattformen wie Cloud Functions und Cloud Run oder gegebenenfalls andere Plattformen einzubeziehen.
In diesem Codelab erfahren Sie, wie Sie von App Engine Blobstore zu Cloud Storage migrieren. Es gibt auch implizite Migrationen aus folgenden Quellen:
webapp2
-Web-Framework zu Flask (in Modul 1 behandelt)- App Engine NDB für den Datastore-Zugriff auf Cloud NDB (wird in Modul 2 behandelt)
- Python 2 bis 3 (die migrierte Anwendung ist sowohl mit Python 2 als auch mit Python 3 kompatibel)
In den zugehörigen Migrationsmodulen finden Sie weitere Schritt-für-Schritt-Informationen.
Sie werden lernen,
- Verwendung der App Engine Blobstore API/-Bibliothek hinzufügen
- Nutzeruploads in den Blobstore-Dienst speichern
- Auf den nächsten Schritt der Migration zu Cloud Storage vorbereiten
Voraussetzungen
- Ein Google Cloud Platform-Projekt mit einem aktiven GCP-Rechnungskonto
- Grundlegende Python-Kenntnisse
- Erfahrung mit gängigen Linux-Befehlen
- Grundkenntnisse zum Entwickeln und Bereitstellen von App Engine-Anwendungen
- Eine funktionierende App Engine-Anwendung für Modul 15: Schließen Sie das Codelab für Modul 15 ab (empfohlen) oder kopieren Sie die Anwendung für Modul 15 aus dem Repository.
Umfrage
Wie möchten Sie diese Anleitung nutzen?
<ph type="x-smartling-placeholder">Wie würden Sie Ihre Erfahrung mit Python bewerten?
<ph type="x-smartling-placeholder">Wie würden Sie Ihre Erfahrungen im Umgang mit Google Cloud-Diensten bewerten?
<ph type="x-smartling-placeholder">2. Hintergrund
Dieses Codelab beginnt mit der Beispielanwendung aus Modul 15 und zeigt, wie Sie von Blobstore (und NDB) zu Cloud Storage (und Cloud NDB) migrieren. Beim Migrationsprozess werden Abhängigkeiten von den gebündelten Legacy-Diensten von App Engine ersetzt, mit denen Sie Ihre Anwendungen bei Bedarf auf eine andere serverlose Cloud-Plattform oder eine andere Hostingplattform verschieben können.
Diese Migration erfordert etwas mehr Aufwand als die anderen Migrationen in dieser Reihe. Blobstore hat Abhängigkeiten vom ursprünglichen Webanwendungs-Framework. Aus diesem Grund verwendet die Beispielanwendung das Framework webapp2 anstelle von Flask. In dieser Anleitung werden Migrationen zu Cloud Storage, Cloud NDB, Flask und Python 3 beschrieben.
Die App registriert weiterhin „Besuche“ von Endnutzern. und zeigt die zehn neuesten an. Im vorherigen Codelab (Modul 15) wurden jedoch neue Funktionen für die Blobstore-Nutzung hinzugefügt: Die Anwendung fordert die Endnutzer auf, ein Artefakt (eine Datei) für ihren Besuch hochzuladen. Nutzer können das jetzt tun oder „Überspringen“ auswählen deaktivieren können. Unabhängig von der Entscheidung des Nutzers wird auf der nächsten Seite die gleiche Ausgabe wie in früheren Versionen dieser App angezeigt, wobei die letzten Besuche angezeigt werden. Ein weiterer Vorteil ist, dass Besuche mit entsprechenden Artefakten eine „Aussicht“ bieten. Link zum Anzeigen des Besuchsartefakts. In diesem Codelab werden die oben genannten Migrationen implementiert und die beschriebene Funktionalität beibehalten.
3. Einrichtung/Vorarbeit
Bevor wir zum Hauptteil des Tutorials kommen, richten wir unser Projekt ein, rufen den Code ab und stellen dann die Referenzanwendung bereit, damit wir wissen, dass wir mit funktionierendem Code beginnen.
1. Projekt einrichten
Wenn Sie die Modul 15-App bereits bereitgestellt haben, empfehlen wir, dasselbe Projekt (und denselben Code) wiederzuverwenden. Alternativ können Sie ein ganz neues Projekt erstellen oder ein anderes vorhandenes Projekt wiederverwenden. Achten Sie darauf, dass das Projekt ein aktives Rechnungskonto hat und App Engine aktiviert ist.
2. Baseline-Beispiel-App abrufen
Eine der Voraussetzungen für dieses Codelab ist eine funktionierende Beispiel-App für Modul 15. Wenn Sie die E-Mail-Adresse nicht haben, finden Sie sie in Modul 15 „START“. (Link unten). Dieses Codelab führt Sie durch die einzelnen Schritte und endet mit Code, der dem in Modul 16 „FINISH“ ähnelt. Ordner.
- START: Modul 15 Ordner (Python 2)
- FINISH: Modul 16 Ordner (Python 2)
- Gesamtes Repository (um die ZIP-Datei zu klonen oder herunterzuladen)
Das Verzeichnis der START-Dateien in Modul 15 sollte wie folgt aussehen:
$ ls README.md app.yaml main-gcs.py main.py templates
Die Datei main-gcs.py
ist eine alternative Version von main.py
aus Modul 15. Sie ermöglicht die Auswahl eines Cloud Storage-Buckets, der vom Standard der zugewiesenen URL einer Anwendung abweicht, der auf der Projekt-ID basiert: PROJECT_ID
.appspot.com
. Diese Datei spielt in diesem (Modul 16) Codelab keine andere Rolle, außer dass ähnliche Migrationstechniken auf diese Datei angewendet werden können.
3. Referenz-App noch einmal bereitstellen
Sie müssen die verbleibenden Schritte jetzt ausführen:
- Machen Sie sich noch einmal mit dem
gcloud
-Befehlszeilentool vertraut - Beispielanwendung mit
gcloud app deploy
noch einmal bereitstellen - Prüfen, ob die Anwendung in App Engine problemlos ausgeführt wird
Nachdem Sie diese Schritte erfolgreich ausgeführt haben, und prüfen, ob Ihre Modul 15-App funktioniert. Auf der ersten Seite werden Nutzer mit einem Formular begrüßt, in dem sie zum Hochladen einer Besuchsartefaktdatei und der Option „Überspringen“ aufgefordert werden. auf, um die Funktion zu deaktivieren:
Sobald Nutzer eine Datei hochgeladen oder übersprungen haben, rendert die App die bekannten „zuletzt besuchten Orte“. Seite:
Besuche mit einem Artefakt haben eine „Ansicht“ Link rechts neben dem Zeitstempel des Besuchs, um das Artefakt anzuzeigen (oder herunterzuladen). Sobald Sie die Funktionalität der Anwendung überprüft haben, können Sie von den Legacy-Diensten von App Engine (Web-App2, NDB, Blobstore) zu modernen Alternativen (Flask, Cloud NDB, Cloud Storage) migrieren.
4. Konfigurationsdateien aktualisieren
Für die aktualisierte Version der App kommen drei Konfigurationsdateien zum Einsatz. Die erforderlichen Aufgaben sind:
- Aktualisieren Sie die erforderlichen integrierten Bibliotheken von Drittanbietern in
app.yaml
und lassen Sie die Tür zu einer Python 3-Migration offen. - Fügen Sie einen
requirements.txt
hinzu, der alle erforderlichen Bibliotheken angibt, die nicht integriert sind - Füge
appengine_config.py
hinzu, damit die App sowohl integrierte als auch nicht integrierte Bibliotheken von Drittanbietern unterstützt
app.yaml
Bearbeiten Sie die Datei app.yaml
, indem Sie den Abschnitt libraries
aktualisieren. Entferne jinja2
und füge grpcio
, setuptools
und ssl
hinzu. Wählen Sie die neueste Version aus, die für alle drei Bibliotheken verfügbar ist. Fügen Sie außerdem die Python 3-Anweisung runtime
hinzu, aber auskommentiert. Wenn Sie fertig sind, sollte dies so aussehen (wenn Sie Python 3.9 ausgewählt haben):
VORHER:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: jinja2
version: latest
NACHHER:
#runtime: python39
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: grpcio
version: latest
- name: setuptools
version: latest
- name: ssl
version: latest
Die Änderungen betreffen hauptsächlich die integrierten Python 2-Bibliotheken, die auf App Engine-Servern verfügbar sind, sodass Sie sie nicht selbst bündeln müssen. Wir haben Jinja2 entfernt, weil es mit Flask geliefert wird, das wir zu reqs.txt hinzufügen werden. Wenn Google Cloud-Clientbibliotheken verwendet werden, z. B. die für Cloud NDB und Cloud Storage, werden grpcio und setuptools benötigt. Schließlich benötigt Cloud Storage selbst die SSL-Bibliothek. Die oben auskommentierte Laufzeitanweisung ist für den Fall gedacht, dass Sie diese Anwendung auf Python 3 portieren möchten. Am Ende dieses Tutorials wird dieses Thema behandelt.
requirements.txt
Fügen Sie eine requirements.txt
-Datei hinzu, für die das Flask-Framework sowie die Cloud NDB- und Cloud Storage-Clientbibliotheken erforderlich sind. Keine dieser Bibliotheken ist integriert. Erstellen Sie die Datei mit folgendem Inhalt:
flask
google-cloud-ndb
google-cloud-storage
Die Python 2 App Engine-Laufzeit erfordert eine Selbstbündelung nicht integrierter Drittanbieterbibliotheken. Führen Sie daher den folgenden Befehl aus, um diese Bibliotheken im lib-Ordner zu installieren:
pip install -t lib -r requirements.txt
Wenn Sie sowohl Python 2 als auch 3 auf Ihrem Entwicklungscomputer haben, müssen Sie möglicherweise den Befehl pip2 verwenden, um sicherzustellen, dass die Python 2-Versionen dieser Bibliotheken abgerufen werden. Nach dem Upgrade auf Python 3 müssen Sie sich nicht mehr selbst bündeln.
appengine_config.py
Füge eine appengine_config.py
-Datei hinzu, die integrierte und nicht integrierte Bibliotheken von Drittanbietern unterstützt. Erstellen Sie die Datei mit folgendem Inhalt:
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)
Die gerade ausgeführten Schritte sollten den Schritten im Abschnitt Bibliotheken für Python 2-Anwendungen installieren der App Engine-Dokumentation ähneln oder identisch sein. Genauer gesagt sollte der Inhalt von appengine_config.py
mit dem Inhalt in Schritt 5 übereinstimmen.
Die Arbeit an den Konfigurationsdateien ist abgeschlossen, also machen wir mit der Anwendung weiter.
5. Anwendungsdateien ändern
Importe
Zu den ersten Änderungen für main.py
gehört das Austauschen aller Komponenten, die ersetzt werden sollen. Folgendes wird sich ändern:
webapp2
wird durch Flask ersetzt- Verwenden Sie nicht Jinja2 aus
webapp2_extras
, sondern die Jinja2-Version, die in Flask enthalten ist. - App Engine Blobstore und NDB wurden durch Cloud NDB und Cloud Storage ersetzt
- Die Blobstore-Handler in
webapp
werden durch eine Kombination aus demio
-Standardbibliotheksmodul, Flask- undwerkzeug
-Dienstprogrammen ersetzt - Blobstore schreibt standardmäßig in einen Cloud Storage-Bucket, der nach der URL Ihrer Anwendung benannt ist (
PROJECT_ID.appspot.com
). Da wir Daten zur Cloud Storage-Clientbibliothek übertragen, wirdgoogle.auth
verwendet, um die Projekt-ID abzurufen und denselben Bucket-Namen anzugeben. Sie können den Bucket-Namen ändern, da er nicht mehr hartcodiert ist.
VORHER:
import webapp2
from webapp2_extras import jinja2
from google.appengine.ext import blobstore, ndb
from google.appengine.ext.webapp import blobstore_handlers
Implementieren Sie die Änderungen in der Liste oben, indem Sie den aktuellen Importabschnitt in main.py
durch das Code-Snippet unten ersetzen.
NACHHER:
import io
from flask import (Flask, abort, redirect, render_template,
request, send_file, url_for)
from werkzeug.utils import secure_filename
import google.auth
from google.cloud import exceptions, ndb, storage
Initialisierung und unnötige Jinja2-Unterstützung
Der nächste zu ersetzende Codeblock ist der BaseHandler
, der die Verwendung von Jinja2 aus webapp2_extras
angibt. Dies ist überflüssig, da Jinja2 im Lieferumfang von Flask enthalten ist und die Standard-Engine für Vorlagen ist. Entfernen Sie diese Funktion also.
Instanziieren Sie in Modul 16 Objekte, die in der älteren App nicht vorhanden waren. Dazu gehören die Initialisierung der Flask-Anwendung und das Erstellen von API-Clients für Cloud NDB und Cloud Storage. Schließlich fügen wir den Namen des Cloud Storage-Buckets wie oben im Abschnitt „Importe“ beschrieben zusammen. Hier sind die Vorher und nach der Implementierung dieser Aktualisierungen:
VORHER:
class BaseHandler(webapp2.RequestHandler):
'Derived request handler mixing-in Jinja2 support'
@webapp2.cached_property
def jinja2(self):
return jinja2.get_jinja2(app=self.app)
def render_response(self, _template, **context):
self.response.write(self.jinja2.render_template(_template, **context))
NACHHER:
app = Flask(__name__)
ds_client = ndb.Client()
gcs_client = storage.Client()
_, PROJECT_ID = google.auth.default()
BUCKET = '%s.appspot.com' % PROJECT_ID
Datastore-Zugriff aktualisieren
Cloud NDB ist größtenteils mit App Engine NDB kompatibel. Ein bereits behandelter Unterschied ist die Notwendigkeit eines API-Clients. Bei letzterem muss der Zugriff auf den Datenspeicher vom Python-Kontextmanager des API-Clients gesteuert werden. Im Wesentlichen bedeutet das, dass alle Datastore-Zugriffsaufrufe mit der Cloud NDB-Clientbibliothek nur innerhalb von Python-with
-Blöcken erfolgen können.
Das ist eine Änderung: zum anderen, dass Blobstore und seine Objekte, z.B. BlobKey
s werden von Cloud Storage nicht unterstützt. Ändern Sie file_blob
daher in ndb.StringProperty
. Unten sehen Sie die Datenmodellklasse und die aktualisierten Funktionen store_visit()
und fetch_visits()
, die diese Änderungen widerspiegeln:
VORHER:
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
file_blob = ndb.BlobKeyProperty()
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_blob=upload_key).put()
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)
file_blob = ndb.StringProperty()
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_blob=upload_key).put()
def fetch_visits(limit):
'get most recent visits'
with ds_client.context():
return Visit.query().order(-Visit.timestamp).fetch(limit)
Hier ist eine bildliche Darstellung der bisher vorgenommenen Änderungen:
Handler aktualisieren
Upload-Handler
Handler in webapp2
sind Klassen, während sie Funktionen in Flask sind. Anstelle einer HTTP-Verbmethode verwendet Flask das Verb zum Dekorieren der Funktion. Blobstore und die zugehörigen webapp
-Handler werden durch Funktionen von Cloud Storage sowie von Flask und seinen Dienstprogrammen ersetzt:
VORHER:
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
'Upload blob (POST) handler'
def post(self):
uploads = self.get_uploads()
blob_id = uploads[0].key() if uploads else None
store_visit(self.request.remote_addr, self.request.user_agent, blob_id)
self.redirect('/', code=307)
NACHHER:
@app.route('/upload', methods=['POST'])
def upload():
'Upload blob (POST) handler'
fname = None
upload = request.files.get('file', None)
if upload:
fname = secure_filename(upload.filename)
blob = gcs_client.bucket(BUCKET).blob(fname)
blob.upload_from_file(upload, content_type=upload.content_type)
store_visit(request.remote_addr, request.user_agent, fname)
return redirect(url_for('root'), code=307)
Einige Hinweise zu dieser Aktualisierung:
- Statt eines
blob_id
werden Dateiartefakte jetzt anhand des Dateinamens (fname
) identifiziert, sofern vorhanden, und ansonsten anhand vonNone
(der Nutzer hat das Hochladen einer Datei deaktiviert). - Die Blobstore-Handler abstrahieren den Uploadprozess von den Nutzern, aber Cloud Storage tut dies nicht. Daher sehen Sie den neu hinzugefügten Code, der das Blob-Objekt und den Speicherort der Datei (Bucket) festlegt, sowie den Aufruf, der den eigentlichen Upload durchführt. (
upload_from_file()
). webapp2
verwendet eine Routingtabelle am Ende der Anwendungsdatei, während in jedem dekorierten Handler Flask-Routen zu finden sind.- Beide Handler schließen ihre Funktionalität ab, indem sie zur Startseite (
/
) weitergeleitet werden, während diePOST
-Anfrage mit einem HTTP 307-Rückgabecode beibehalten wird.
Download-Handler
Die Aktualisierung des Download-Handlers folgt einem ähnlichen Muster wie der Upload-Handler, nur es muss viel weniger Code überprüft werden. Ersetzen Sie die Blobstore- und webapp
-Funktionen durch die Cloud Storage- und Flask-Entsprechungen:
VORHER:
class ViewBlobHandler(blobstore_handlers.BlobstoreDownloadHandler):
'view uploaded blob (GET) handler'
def get(self, blob_key):
self.send_blob(blob_key) if blobstore.get(blob_key) else self.error(404)
NACHHER:
@app.route('/view/<path:fname>')
def view(fname):
'view uploaded blob (GET) handler'
blob = gcs_client.bucket(BUCKET).blob(fname)
try:
media = blob.download_as_bytes()
except exceptions.NotFound:
abort(404)
return send_file(io.BytesIO(media), mimetype=blob.content_type)
Hinweise zu diesem Update:
- Auch hier werden Handler-Funktionen mit ihrer Route dekoriert, während
webapp
dies in einer Routingtabelle am unteren Rand ausführt. Daher wird die Musterabgleichssyntax von Flask (('/view/([^/]+)?'
) von der von Flask ('/view/<path:fname>'
) unterschieden. - Wie beim Upload-Handler ist bei Cloud Storage noch etwas mehr Arbeit für Funktionen erforderlich, die von den Blobstore-Handlern abstrahiert werden: die Identifizierung der betreffenden Datei (Blob) und das explizite Herunterladen des Binärprogramms im Vergleich zum einzelnen
send_blob()
-Methodenaufruf des Blobstore-Handlers. - In beiden Fällen wird der HTTP-Fehler 404 an den Nutzer zurückgegeben, wenn kein Artefakt gefunden wird.
Haupt-Handler
Die letzten Änderungen an der Hauptanwendung werden im Haupt-Handler vorgenommen. Die HTTP-Verbmethoden webapp2
werden durch eine einzelne Funktion ersetzt, die ihre Funktionen kombiniert. Ersetzen Sie die Klasse MainHandler
durch die Funktion root()
und entfernen Sie die Routingtabelle webapp2
wie unten gezeigt:
VORHER:
class MainHandler(BaseHandler):
'main application (GET/POST) handler'
def get(self):
self.render_response('index.html',
upload_url=blobstore.create_upload_url('/upload'))
def post(self):
visits = fetch_visits(10)
self.render_response('index.html', visits=visits)
app = webapp2.WSGIApplication([
('/', MainHandler),
('/upload', UploadHandler),
('/view/([^/]+)?', ViewBlobHandler),
], debug=True)
NACHHER:
@app.route('/', methods=['GET', 'POST'])
def root():
'main application (GET/POST) handler'
context = {}
if request.method == 'GET':
context['upload_url'] = url_for('upload')
else:
context['visits'] = fetch_visits(10)
return render_template('index.html', **context)
Im Grunde sind es keine separaten get()
- und post()
-Methoden, sondern eine if-else
-Anweisung in root()
. Da root()
eine einzelne Funktion ist, gibt es nur einen Aufruf zum Rendern der Vorlage sowohl für GET
als auch für POST
. In webapp2
ist dies nicht wirklich möglich.
Hier ist eine bildliche Darstellung dieser zweiten und letzten Änderungen an main.py
:
(optional) „Optimierung“ der Abwärtskompatibilität
Die oben erstellte Lösung funktioniert also perfekt... aber nur, wenn Sie bei null anfangen und keine Dateien haben, die von Blobstore erstellt wurden. Da wir die Anwendung so aktualisiert haben, dass Dateien anhand des Dateinamens und nicht nach BlobKey
identifiziert werden, kann die abgeschlossene Anwendung für Modul 16 in der vorliegenden Form keine Blobstore-Dateien aufrufen. Anders ausgedrückt: Bei dieser Migration haben wir eine nicht abwärtskompatible Änderung vorgenommen. Wir präsentieren jetzt eine alternative Version von main.py
mit dem Namen main-migrate.py
(im Repository gefunden), die versucht, diese Lücke zu schließen.
Die erste „Erweiterung“ Zur Unterstützung von in Blobstore erstellten Dateien gibt es ein Datenmodell mit einem BlobKeyProperty
(zusätzlich zu einem StringProperty
für von Cloud Storage erstellte Dateien):
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
file_blob = ndb.BlobKeyProperty() # backwards-compatibility
file_gcs = ndb.StringProperty()
Das Attribut file_blob
wird verwendet, um von Blobstore erstellte Dateien zu identifizieren, während file_gcs
für Cloud Storage-Dateien vorgesehen ist. Speichern Sie nun beim Erstellen neuer Besuche explizit einen Wert in file_gcs
statt in file_blob
, sodass „store_visit“ etwas anders aussieht:
VORHER:
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_blob=upload_key).put()
NACHHER:
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_gcs=upload_key).put()
Beim Abrufen der letzten Besuche "normalisieren" bevor Sie sie an die Vorlage senden:
VORHER:
@app.route('/', methods=['GET', 'POST'])
def root():
'main application (GET/POST) handler'
context = {}
if request.method == 'GET':
context['upload_url'] = url_for('upload')
else:
context['visits'] = fetch_visits(10)
return render_template('index.html', **context)
NACHHER:
@app.route('/', methods=['GET', 'POST'])
def root():
'main application (GET/POST) handler'
context = {}
if request.method == 'GET':
context['upload_url'] = url_for('upload')
else:
context['visits'] = etl_visits(fetch_visits(10))
return render_template('index.html', **context)
Bestätigen Sie als Nächstes, dass file_blob
oder file_gcs
(oder keines von beiden) vorhanden ist. Wenn eine Datei verfügbar ist, wählen Sie die vorhandene aus und verwenden Sie diese ID (BlobKey
für von Blobstore erstellte Dateien oder Dateiname für von Cloud Storage erstellte Dateien). Wenn wir von „In Cloud Storage erstellte Dateien“ sprechen, sind Dateien, die mit der
Cloud Storage-Clientbibliothek erstellt wurden. Blobstore schreibt auch in Cloud Storage, aber in diesem Fall wären das von Blobstore erstellte Dateien.
Und was ist die etl_visits()
-Funktion, die zum Normalisieren oder ETL (Extrahieren, Transformieren und Laden) der Daten für den Endnutzer verwendet wird? Sie sieht so aus:
def etl_visits(visits):
return [{
'visitor': v.visitor,
'timestamp': v.timestamp,
'file_blob': v.file_gcs if hasattr(v, 'file_gcs') \
and v.file_gcs else v.file_blob
} for v in visits]
Wahrscheinlich sieht es so aus, wie Sie es erwartet haben: Der Code durchläuft alle Besuche und nimmt bei jedem Besuch die Besucher- und Zeitstempeldaten wörtlich. Anschließend wird geprüft, ob file_gcs
oder file_blob
vorhanden ist. Wenn ja, wird eine davon ausgewählt (oder None
, wenn keine vorhanden ist).
Hier sehen Sie die Unterschiede zwischen main.py
und main-migrate.py
:
Wenn Sie von Grund auf ohne Blobstore-Dateien beginnen möchten, sollten Sie main.py
verwenden. Wenn Sie jedoch Dateien übertragen möchten, die sowohl von Blobstore als auch Cloud Storage erstellt wurden, sollten Sie sich main-migrate.py
als Beispiel für den Umgang mit Szenarien ansehen, um Migrationen für Ihre eigenen Anwendungen zu planen. Bei komplexen Migrationen treten wahrscheinlich Sonderfälle auf. Deshalb soll dieses Beispiel zeigen, dass die Modernisierung echter Anwendungen mit echten Daten stärker ist.
6. Zusammenfassung/Bereinigung
In diesem Abschnitt wird dieses Codelab abgeschlossen. Dazu wird die App bereitgestellt und geprüft, ob sie wie vorgesehen und in allen ausgegebenen Ausgabedaten funktioniert. Führen Sie nach der App-Überprüfung alle Bereinigungsschritte durch und erwägen Sie die nächsten Schritte.
Anwendung bereitstellen und prüfen
Bevor Sie Ihre App noch einmal bereitstellen, führen Sie pip install -t lib -r requirements.txt
aus, um diese selbst gebündelten Drittanbieterbibliotheken aus dem lib-Ordner zu entfernen. Wenn Sie die abwärtskompatible Lösung ausführen möchten, benennen Sie main-migrate.py
zuerst in main.py
um. Führen Sie nun gcloud app deploy
aus und prüfen Sie, ob die App identisch mit Modul 15 funktioniert. Der Formularbildschirm sieht so aus:
Die Seite mit den letzten Besuchen sieht so aus:
Herzlichen Glückwunsch! Sie haben dieses Codelab abgeschlossen, in dem App Engine Blobstore durch Cloud Storage, App Engine NDB durch Cloud NDB und webapp2
durch Flask ersetzt wurde. Ihr Code sollte jetzt mit dem Inhalt im Ordner FINISH (Modul 16) übereinstimmen. Die Alternative main-migrate.py
ist auch in diesem Ordner vorhanden.
Python 3 „Migration“
Sie benötigen lediglich die auskommentierte runtime
-Anweisung von Python 3 am Anfang von app.yaml
, um diese Anwendung zu Python 3 zu portieren. Der Quellcode selbst ist bereits mit Python 3 kompatibel, sodass dort keine Änderungen erforderlich sind. Führen Sie die folgenden Schritte aus, um sie als Python 3-Anwendung bereitzustellen:
- Entfernen Sie die Kommentarzeichen von der Python 3-Anweisung
runtime
oben inapp.yaml
. - Löschen Sie alle anderen Zeilen in
app.yaml
. - Löschen Sie die Datei
appengine_config.py
. (in der Python 3-Laufzeit nicht verwendet) - Löschen Sie den Ordner
lib
, falls vorhanden. (für Python 3-Laufzeit nicht erforderlich)
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:
- Der App Engine Blobstore-Dienst fällt unter die Kontingente und Limits für gespeicherte Daten. Beachten Sie dies bitte sowie die Preisübersicht für gebündelte Legacy-Dienste.
- Cloud Storage bietet für bestimmte Regionen eine kostenlose Stufe. finden Sie auch auf der Seite mit den allgemeinen Preisen.
- Der App Engine Datastore-Dienst wird von Cloud Datastore (Cloud Firestore im Datastore-Modus) bereitgestellt, der ebenfalls eine kostenlose Stufe hat. finden Sie auf der Preisseite weitere Informationen.“
Wenn Sie von Modul 15 zu 16 migriert haben, befinden sich immer noch Daten in Blobstore. Daher werden die Preisinformationen oben aufgeführt.
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 Push-Aufgaben der App Engine-Aufgabenwarteschlange zu Cloud Tasks
- Module 12–13: Migration von App Engine Memcache zu Cloud Memorystore
- Module 18–19: Migration von App Engine-Aufgabenwarteschlange (Pull-Aufgaben) zu 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
Codelab-Probleme/Feedback
Wenn Sie Probleme mit diesem Codelab feststellen, suchen Sie bitte zuerst nach dem Problem, bevor Sie es einreichen. Links zum Suchen und Erstellen neuer Ausgaben:
Migrationsressourcen
In der folgenden Tabelle finden Sie Links zu den Repository-Ordnern für Modul 15 (START) und Modul 16 (FINISH). 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 15 | – | |
Modul 16 (dieses Codelab) | (entspricht Python 2) |
Online-Ressourcen
Nachfolgend finden Sie Onlineressourcen, die für diese Anleitung relevant sein könnten:
App Engine Blobstore und Cloud Storage
- App Engine Blobstore-Dienst
- Zur Cloud Storage-Clientbibliothek migrieren
- Cloud Storage-Startseite
- Cloud Storage-Dokumentation
App Engine-Plattform
- App Engine-Dokumentation
- Python 2-Laufzeit der App Engine (Standardumgebung)
- Integrierte App Engine-Bibliotheken in Python 2 App Engine verwenden
- Python 3-Laufzeit von App Engine (Standardumgebung)
- Unterschiede zwischen Python 2 und 3 Laufzeiten der App Engine (Standardumgebung)
- Python 2 zu 3 Migrationsanleitung für App Engine (Standardumgebung)
- Informationen zu Preisen und Kontingenten für App Engine
- Einführung der App Engine-Plattform der zweiten Generation (2018)
- Vergleichen Sie zuerst und Plattformen der zweiten Generation
- Langzeitsupport für Legacy-Laufzeiten
- Repository mit Beispielen für die Migration der Dokumentation
- Repository für Migrationsbeispiele
Weitere Cloud-Informationen
- Python auf der Google Cloud Platform
- Google Cloud-Clientbibliotheken für Python
- „Immer kostenlos“ von Google Cloud Stufe
- Google Cloud SDK (
gcloud
-Befehlszeilentool) - Gesamte Google Cloud-Dokumentation
Python
- Vorlagensysteme von Django und Jinja2
webapp2
-Web-Framework- Dokumentation zu
webapp2
webapp2_extras
-Linkswebapp2_extras
Jinja2-Dokumentation- Flask-Web-Framework
Videos
- Serverlose Migrationsstation
- Serverlose Expeditionen
- Google Cloud Tech abonnieren
- Google Developers abonnieren
Lizenz
Dieser Text ist mit einer Creative Commons Attribution 2.0 Generic License lizenziert.