1. Présentation
La série d'ateliers de programmation Serverless Migration Station (tutoriels pratiques à suivre à votre rythme) et les vidéos associées sont destinées à aider les développeurs Google Cloud sans serveur à moderniser leurs applications en les guidant tout au long d'une ou plusieurs migrations, principalement en les aidant à abandonner les anciens services. Cela rend vos applications plus portables et vous offre plus d'options et de flexibilité, ce qui vous permet de vous intégrer à une plus large gamme de produits Cloud et d'y accéder, et de passer plus facilement aux versions linguistiques plus récentes. Bien qu'elle se concentre initialement sur les premiers utilisateurs de Cloud, principalement les développeurs App Engine (environnement standard), cette série est suffisamment large pour inclure d'autres plates-formes sans serveur comme Cloud Functions et Cloud Run, ou ailleurs si nécessaire.
Cet atelier de programmation vous explique comment migrer d'App Engine Blobstore vers Cloud Storage. Il existe également des migrations implicites depuis :
- Framework Web
webapp2vers Flask (couvert par le module 1) - App Engine NDB vers Cloud NDB pour l'accès à Datastore (couvert par le module 2)
- Python 2 vers Python 3 (l'application migrée est compatible avec Python 2 et Python 3)
Pour obtenir des informations plus détaillées, consultez les modules de migration associés.
Vous apprendrez à
- Ajouter l'utilisation de l'API/bibliothèque Blobstore d'App Engine
- Stocker les importations des utilisateurs dans le service Blobstore
- Préparer la prochaine étape de la migration vers Cloud Storage
Prérequis
- Un projet Google Cloud Platform avec un compte de facturation GCP actif
- Des connaissances de base en Python
- Une connaissance correcte des commandes Linux courantes
- Des connaissances de base du développement et du déploiement d'applications App Engine
- Une application App Engine du module 15 fonctionnelle : suivez l'atelier de programmation du module 15 (recommandé) ou copiez l'application du module 15 depuis le dépôt.
Enquête
Comment allez-vous utiliser ce tutoriel ?
Quel est votre niveau d'expérience avec Python ?
Quel est votre niveau d'expérience avec les services Google Cloud ?
2. Arrière-plan
Dans cet atelier de programmation, vous allez utiliser l'application exemple du module 15 et découvrir comment migrer de Blobstore (et NDB) vers Cloud Storage (et Cloud NDB). Le processus de migration consiste à remplacer les dépendances sur les anciens services groupés d'App Engine, ce qui vous permet de migrer vos applications vers une autre plate-forme Cloud sans serveur ou une autre plate-forme d'hébergement si vous le souhaitez.
Cette migration nécessite un peu plus d'efforts que les autres migrations de cette série. Blobstore dépend du framework webapp d'origine. C'est pourquoi l'exemple d'application utilise le framework webapp2 au lieu de Flask. Ce tutoriel présente des migrations vers Cloud Storage, Cloud NDB, Flask et Python 3.
L'application enregistre toujours les "visites" des utilisateurs finaux et affiche les dix plus récentes, mais l'atelier de programmation précédent (module 15) a ajouté une nouvelle fonctionnalité pour tenir compte de l'utilisation de Blobstore : l'application invite les utilisateurs finaux à importer un artefact (un fichier) correspondant à leur "visite". Les utilisateurs peuvent le faire ou sélectionner "Ignorer" pour refuser. Quelle que soit la décision de l'utilisateur, la page suivante affiche la même sortie que les versions précédentes de cette application, en affichant les visites les plus récentes. Autre particularité : les visites avec des artefacts correspondants comportent un lien "Afficher" permettant d'afficher l'artefact d'une visite. Cet atelier de programmation implémente les migrations mentionnées précédemment tout en préservant la fonctionnalité décrite.
3. Configuration/Préparation
Avant de passer à la partie principale de ce tutoriel, nous allons configurer notre projet, obtenir le code et déployer l'application de base pour nous assurer de bien utiliser du code fonctionnel.
1. Configurer le projet
Si vous avez déjà déployé l'application du module 15, nous vous recommandons de réutiliser le même projet (et le même code). Vous pouvez également créer un projet ou réutiliser un autre projet existant. Assurez-vous que le projet dispose d'un compte de facturation actif et qu'App Engine est activé.
2. Obtenir un exemple d'application de référence
L'une des conditions préalables à cet atelier de programmation est de disposer d'un exemple d'application fonctionnel du module 15. Si vous n'en avez pas, vous pouvez l'obtenir dans le dossier "START" du module 15 (lien ci-dessous). Cet atelier de programmation vous guide pour chaque étape jusqu'à obtenir un code similaire à celui du dossier "FINISH" du module 16.
- START : Dossier du module 15 (Python 2)
- FINISH : Dossier du module 16 (Python 2)
- Dépôt complet (pour cloner ou télécharger le fichier ZIP)
Le répertoire des fichiers de départ du module 15 doit se présenter comme suit :
$ ls README.md app.yaml main-gcs.py main.py templates
Le fichier main-gcs.py est une version alternative de main.py du module 15. Il permet de sélectionner un bucket Cloud Storage différent de celui par défaut d'une URL attribuée à une application en fonction de l'ID du projet : PROJECT_ID.appspot.com. Ce fichier ne joue aucun rôle dans cet atelier de programmation (module 16), si ce n'est que des techniques de migration similaires peuvent lui être appliquées si vous le souhaitez.
3. (Re)Déployer l'application de référence
Étapes préliminaires restantes :
- Familiarisez-vous avec l'outil de ligne de commande
gcloud - Redéployez l'exemple d'application avec
gcloud app deploy - Vérifier que l'application s'exécute sans problème sur App Engine
Une fois ces étapes effectuées, vérifiez que votre application du module 15 fonctionne. La page d'accueil présente aux utilisateurs un formulaire les invitant à importer un fichier d'artefact de visite, ainsi qu'une option leur permettant de refuser en cliquant sur un bouton "Ignorer" :

Une fois que les utilisateurs ont importé un fichier ou ignoré cette étape, l'application affiche la page "Visites récentes" qu'ils connaissent bien :

Les visites comportant un artefact sont associées à un lien "Afficher" à droite de l'horodatage de la visite, qui permet d'afficher (ou de télécharger) l'artefact. Une fois que vous avez confirmé la fonctionnalité de l'application, vous êtes prêt à migrer des anciens services App Engine (webapp2, NDB, Blobstore) vers des alternatives contemporaines (Flask, Cloud NDB, Cloud Storage).
4. Mettre à jour les fichiers de configuration
Trois fichiers de configuration entrent en jeu pour la version mise à jour de notre application. Les tâches requises sont les suivantes :
- Mettre à jour les bibliothèques tierces intégrées requises dans
app.yamlet laisser la porte ouverte à une migration vers Python 3 - Ajoutez un
requirements.txtqui spécifie toutes les bibliothèques requises qui ne sont pas intégrées. - Ajoutez
appengine_config.pypour que l'application soit compatible avec les bibliothèques tierces intégrées et non intégrées.
app.yaml
Modifiez votre fichier app.yaml en mettant à jour la section libraries. Supprimez jinja2 et ajoutez grpcio, setuptools et ssl. Choisissez la dernière version disponible pour les trois bibliothèques. Ajoutez également la directive Python 3 runtime, mais mettez-la en commentaire. Une fois que vous avez terminé, le résultat doit être semblable à ceci (si vous avez sélectionné Python 3.9) :
AVANT :
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: jinja2
version: latest
APRÈS :
#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
Les modifications concernent principalement les bibliothèques Python 2 intégrées disponibles sur les serveurs App Engine (vous n'avez donc pas besoin de les regrouper vous-même). Nous avons supprimé Jinja2, car il est fourni avec Flask, que nous allons ajouter à reqs.txt. grpcio et setuptools sont nécessaires chaque fois que des bibliothèques clientes Google Cloud, telles que celles pour Cloud NDB et Cloud Storage, sont utilisées. Enfin, Cloud Storage lui-même nécessite la bibliothèque SSL. L'instruction d'exécution commentée en haut de la page est à utiliser lorsque vous serez prêt à transférer cette application vers Python 3. Nous aborderons ce sujet à la fin de ce tutoriel.
requirements.txt
Ajoutez un fichier requirements.txt, qui nécessite le framework Flask, ainsi que les bibliothèques clientes Cloud NDB et Cloud Storage, qui ne sont pas intégrées. Créez le fichier avec le contenu suivant :
flask
google-cloud-ndb
google-cloud-storage
L'environnement d'exécution Python 2 App Engine nécessite l'auto-groupement des bibliothèques tierces non intégrées. Exécutez donc la commande suivante pour installer ces bibliothèques dans le dossier "lib" :
pip install -t lib -r requirements.txt
Si vous avez installé Python 2 et Python 3 sur votre machine de développement, vous devrez peut-être utiliser la commande pip2 pour vous assurer d'obtenir les versions Python 2 de ces bibliothèques. Une fois que vous êtes passé à Python 3, vous n'avez plus besoin de regrouper vous-même les dépendances.
appengine_config.py
Ajoutez un fichier appengine_config.py compatible avec les bibliothèques tierces intégrées et non intégrées. Créez le fichier avec le contenu suivant :
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)
Les étapes que vous venez de suivre devraient être semblables ou identiques à celles listées dans la section Installer des bibliothèques pour les applications Python 2 de la documentation App Engine. Plus précisément, le contenu de appengine_config.py devrait correspondre à celui de l'étape 5.
Le travail sur les fichiers de configuration est terminé. Passons maintenant à l'application.
5. Modifier les fichiers d'application
Importations
Le premier ensemble de modifications pour main.py consiste à remplacer tous les éléments à remplacer. Voici ce qui va changer :
webapp2est remplacé par Flask- Au lieu d'utiliser Jinja2 à partir de
webapp2_extras, utilisez celui fourni avec Flask. - App Engine Blobstore et NDB sont remplacés par Cloud NDB et Cloud Storage
- Les gestionnaires Blobstore dans
webappsont remplacés par une combinaison du module de bibliothèque standardio, de Flask et des utilitaireswerkzeug. - Par défaut, Blobstore écrit dans un bucket Cloud Storage dont le nom est celui de l'URL de votre application (
PROJECT_ID.appspot.com). Étant donné que nous effectuons la migration vers la bibliothèque cliente Cloud Storage,google.authest utilisé pour obtenir l'ID de projet afin de spécifier exactement le même nom de bucket. (Vous pouvez modifier le nom du bucket, car il n'est plus codé en dur.)
AVANT :
import webapp2
from webapp2_extras import jinja2
from google.appengine.ext import blobstore, ndb
from google.appengine.ext.webapp import blobstore_handlers
Implémentez les modifications de la liste ci-dessus en remplaçant la section d'importation actuelle dans main.py par l'extrait de code ci-dessous.
APRÈS :
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
Initialisation et prise en charge inutile de Jinja2
Le bloc de code suivant à remplacer est le BaseHandler qui spécifie l'utilisation de Jinja2 à partir de webapp2_extras. Cette ligne est inutile, car Jinja2 est fourni avec Flask et constitue son moteur de création de modèles par défaut. Supprimez-la.
Du côté du module 16, instanciez les objets que nous n'avions pas dans l'ancienne application. Cela inclut l'initialisation de l'application Flask et la création de clients API pour Cloud NDB et Cloud Storage. Enfin, nous assemblons le nom du bucket Cloud Storage, comme décrit ci-dessus dans la section des importations. Voici les captures d'écran avant et après l'implémentation de ces modifications :
AVANT :
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))
APRÈS :
app = Flask(__name__)
ds_client = ndb.Client()
gcs_client = storage.Client()
_, PROJECT_ID = google.auth.default()
BUCKET = '%s.appspot.com' % PROJECT_ID
Mettre à jour l'accès à Datastore
Cloud NDB est principalement compatible avec App Engine NDB. L'une des différences déjà abordées est la nécessité d'un client API. Une autre différence est que le dernier nécessite que l'accès à Datastore soit contrôlé par le gestionnaire de contexte Python du client API. En d'autres termes, cela signifie que tous les appels d'accès à Datastore à l'aide de la bibliothèque cliente Cloud NDB ne peuvent se produire que dans les blocs Python with.
Il s'agit d'un changement.L'autre changement est que Blobstore et ses objets, par exemple les BlobKey, ne sont pas compatibles avec Cloud Storage. Vous devez donc remplacer file_blob par ndb.StringProperty. Vous trouverez ci-dessous la classe de modèle de données et les fonctions store_visit() et fetch_visits() mises à jour reflétant ces modifications :
AVANT :
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)
APRÈS :
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)
Voici une représentation visuelle des modifications apportées jusqu'à présent :

Mettre à jour les gestionnaires
Gestionnaire d'importation
Les gestionnaires dans webapp2 sont des classes, tandis que dans Flask, ce sont des fonctions. Au lieu d'une méthode de verbe HTTP, Flask utilise le verbe pour décorer la fonction. Blobstore et ses gestionnaires webapp sont remplacés par des fonctionnalités de Cloud Storage, ainsi que par Flask et ses utilitaires :
AVANT :
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)
APRÈS :
@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)
Voici quelques remarques concernant cette mise à jour :
- Au lieu d'un
blob_id, les artefacts de fichier sont désormais identifiés par le nom de fichier (fname) s'il est présent, et parNonedans le cas contraire (l'utilisateur a choisi de ne pas importer de fichier). - Les gestionnaires Blobstore ont abstrait le processus d'importation de ses utilisateurs, mais Cloud Storage ne le fait pas. Vous pouvez donc voir le code nouvellement ajouté qui définit l'objet blob et l'emplacement (bucket) du fichier, ainsi que l'appel qui effectue l'importation proprement dite. (
upload_from_file()). webapp2utilise une table de routage en bas du fichier d'application, tandis que les routes Flask se trouvent dans chaque gestionnaire décoré.- Les deux gestionnaires terminent leur fonctionnalité en redirigeant vers la page d'accueil (
/) tout en conservant la requêtePOSTavec un code de retour HTTP 307.
Gestionnaire de téléchargement
La mise à jour du gestionnaire de téléchargement suit un modèle similaire à celui du gestionnaire d'importation, mais avec beaucoup moins de code à examiner. Remplacez les fonctionnalités Blobstore et webapp par les équivalents Cloud Storage et Flask :
AVANT :
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)
APRÈS :
@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)
Remarques sur cette mise à jour :
- Encore une fois, Flask décore les fonctions de gestionnaire avec leur route, tandis que
webapple fait dans une table de routage en bas. Vous devez donc reconnaître la syntaxe de correspondance de modèle de ce dernier (('/view/([^/]+)?') par rapport à celle de Flask ('/view/<path:fname>'). - Comme pour le gestionnaire d'importation, il faut un peu plus de travail côté Cloud Storage pour la fonctionnalité abstraite par les gestionnaires Blobstore, à savoir l'identification du fichier (blob) en question et le téléchargement explicite du binaire par rapport à l'appel de méthode unique
send_blob()du gestionnaire Blobstore. - Dans les deux cas, une erreur HTTP 404 est renvoyée à l'utilisateur si un artefact est introuvable.
Gestionnaire principal
Les dernières modifications apportées à l'application principale ont lieu dans le gestionnaire principal. Les méthodes de verbe HTTP webapp2 sont remplacées par une seule fonction combinant leurs fonctionnalités. Remplacez la classe MainHandler par la fonction root() et supprimez la table de routage webapp2, comme indiqué ci-dessous :
AVANT :
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)
APRÈS :
@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)
Au lieu de méthodes get() et post() distinctes, il s'agit essentiellement d'une instruction if-else dans root(). De plus, comme root() est une fonction unique, il n'y a qu'un seul appel pour afficher le modèle pour GET et POST, ce qui n'est pas vraiment possible dans webapp2.
Voici une représentation visuelle de ce deuxième et dernier ensemble de modifications apportées à main.py :

(facultatif) "Amélioration" de la rétrocompatibilité
La solution créée ci-dessus fonctionne parfaitement, mais uniquement si vous partez de zéro et que vous n'avez pas de fichiers créés par Blobstore. Étant donné que nous avons mis à jour l'application pour identifier les fichiers par leur nom au lieu de BlobKey, l'application du module 16 telle quelle ne pourra pas afficher les fichiers Blobstore. En d'autres termes, nous avons apporté une modification non rétrocompatible lors de cette migration. Nous présentons maintenant une autre version de main.py appelée main-migrate.py (disponible dans le dépôt) qui tente de combler cette lacune.
La première "extension" permettant de prendre en charge les fichiers créés par Blobstore est un modèle de données qui comporte un BlobKeyProperty (en plus d'un StringProperty pour les fichiers créés par Cloud Storage) :
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()
La propriété file_blob permet d'identifier les fichiers créés par Blobstore, tandis que file_gcs est réservée aux fichiers Cloud Storage. Désormais, lorsque vous créez des visites, stockez explicitement une valeur dans file_gcs au lieu de file_blob. L'événement store_visit se présente donc un peu différemment :
AVANT :
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()
APRÈS :
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()
Lorsque vous récupérez les visites les plus récentes, normalisez les données avant de les envoyer au modèle :
AVANT :
@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)
APRÈS :
@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)
Ensuite, vérifiez l'existence de file_blob ou file_gcs (ou d'aucun des deux). S'il existe un fichier, sélectionnez-le et utilisez son identifiant (BlobKey pour les fichiers créés par Blobstore ou le nom de fichier pour les fichiers créés par Cloud Storage). Lorsque nous parlons de "fichiers créés par Cloud Storage", nous faisons référence aux fichiers créés à l'aide de la bibliothèque cliente Cloud Storage. Blobstore écrit également dans Cloud Storage, mais dans ce cas, il s'agit de fichiers créés par Blobstore.
Plus important encore, qu'est-ce que cette fonction etl_visits() utilisée pour normaliser ou ETL (extraire, transformer et charger) les données pour l'utilisateur final ? Elle se présente comme suit :
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]
Il ressemble probablement à ce que vous attendiez : le code parcourt toutes les visites et, pour chaque visite, prend les données de visiteur et d'horodatage telles quelles, puis vérifie si file_gcs ou file_blob existe et, si c'est le cas, en choisit un (ou None si aucun n'existe).
Voici une illustration des différences entre main.py et main-migrate.py :

Si vous partez de zéro sans fichiers créés par Blobstore, utilisez main.py. Toutefois, si vous effectuez une transition et que vous souhaitez des fichiers d'assistance créés par Blobstore et Cloud Storage, consultez main-migrate.py pour obtenir un exemple de gestion de ce type de scénario. Cela vous aidera à planifier les migrations pour vos propres applications. Lors de migrations complexes, des cas particuliers sont susceptibles de se produire. Cet exemple est donc destiné à montrer une plus grande affinité pour la modernisation d'applications réelles avec des données réelles.
6. Résumé/Nettoyage
Cette section conclut cet atelier de programmation en déployant l'application et en vérifiant qu'elle fonctionne comme prévu et dans toutes les sorties reflétées. Après la validation de l'application, effectuez les étapes de nettoyage et réfléchissez aux prochaines étapes.
Déployer et vérifier l'application
Avant de redéployer votre application, assurez-vous d'exécuter pip install -t lib -r requirements.txt pour obtenir ces bibliothèques tierces auto-groupées dans le dossier "lib". Si vous souhaitez exécuter la solution rétrocompatible, commencez par renommer main-migrate.py en main.py. Exécutez maintenant gcloud app deploy et vérifiez que l'application fonctionne de la même manière que l'application du module 15. L'écran du formulaire ressemble à ceci :

La page des visites les plus récentes se présente comme suit :

Félicitations ! Vous avez terminé cet atelier de programmation qui consistait à remplacer App Engine Blobstore par Cloud Storage, App Engine NDB par Cloud NDB et webapp2 par Flask. Votre code doit maintenant correspondre à celui du dossier FINISH (Module 16). L'autre fichier main-migrate.py est également présent dans ce dossier.
"Migration" vers Python 3
L'instruction Python 3 runtime commentée en haut de app.yaml est tout ce dont vous avez besoin pour migrer cette application vers Python 3. Le code source lui-même est déjà compatible avec Python 3. Aucune modification n'est donc nécessaire. Pour déployer cette application en tant qu'application Python 3, procédez comme suit :
- Décommentez l'instruction Python 3
runtimeen haut deapp.yaml. - Supprimez toutes les autres lignes de
app.yaml. - Supprimez le fichier
appengine_config.py. (non utilisé dans l'environnement d'exécution Python 3) - Supprimez le dossier
libs'il existe. (inutile avec l'environnement d'exécution Python 3)
Effectuer un nettoyage
Général
Si vous avez terminé pour le moment, nous vous recommandons de désactiver votre application App Engine pour éviter d'être facturé. Toutefois, si vous souhaitez effectuer d'autres tests ou expériences, la plate-forme App Engine dispose d'un quota sans frais. Tant que vous ne dépassez pas ce niveau d'utilisation, aucun frais ne devrait vous être facturé. Cela concerne le calcul, mais des frais peuvent également s'appliquer aux services App Engine concernés. Pour en savoir plus, consultez la page de tarification. Si cette migration implique d'autres services Cloud, ceux-ci sont facturés séparément. Dans les deux cas, le cas échéant, consultez la section "Spécifique à cet atelier de programmation" ci-dessous.
Pour être tout à fait transparent, le déploiement sur une plate-forme de calcul sans serveur Google Cloud comme App Engine entraîne de légers coûts de compilation et de stockage. Cloud Build et Cloud Storage disposent chacun de leur propre quota sans frais. Le stockage de cette image utilise une partie de ce quota. Toutefois, il est possible que vous résidiez dans une région où ce niveau sans frais n'est pas disponible. Veillez donc à surveiller votre utilisation de l'espace de stockage pour minimiser les coûts potentiels. Voici quelques "dossiers" Cloud Storage spécifiques que vous devez examiner :
console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/imagesconsole.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com- Les liens de stockage ci-dessus dépendent de votre
PROJECT_IDet de votre *LOC*ation. Par exemple, "us" si votre application est hébergée aux États-Unis.
En revanche, si vous ne souhaitez pas poursuivre avec cette application ni avec d'autres ateliers de programmation de migration associés et que vous souhaitez tout supprimer complètement, arrêtez votre projet.
Spécifique à cet atelier de programmation
Les services listés ci-dessous sont propres à cet atelier de programmation. Pour en savoir plus, consultez la documentation de chaque produit :
- Le service Blobstore d'App Engine relève des quotas et limites de données stockées. Consultez également la page des tarifs des anciens services groupés.
- Cloud Storage propose une version sans frais pour certaines régions. Pour en savoir plus, consultez également sa page générale sur les tarifs.
- Le service App Engine Datastore est fourni par Cloud Datastore (Cloud Firestore en mode Datastore), qui propose également un niveau sans frais. Pour en savoir plus, consultez sa page de tarification."
Notez que si vous avez migré du module 15 vers le module 16, vous aurez toujours des données dans Blobstore. C'est pourquoi nous incluons les informations sur ses tarifs ci-dessus.
Étapes suivantes
Au-delà de ce tutoriel, voici d'autres modules de migration qui se concentrent sur l'abandon des anciens services groupés :
- Module 2 : migrer depuis App Engine
ndbvers Cloud NDB - Modules 7 à 9 : migrer les tâches push de la file d'attente de tâches App Engine vers Cloud Tasks
- Modules 12 et 13 : migrer d'App Engine Memcache vers Cloud Memorystore
- Modules 18 et 19 : migrer depuis la file d'attente de tâches App Engine (tâches de retrait) vers Cloud Pub/Sub
App Engine n'est plus la seule plate-forme sans serveur de Google Cloud. Si vous avez une petite application App Engine ou une application dont les fonctionnalités sont limitées et que vous souhaitez la transformer en microservice autonome, ou si vous souhaitez diviser une application monolithique en plusieurs composants réutilisables, ce sont de bonnes raisons d'envisager de passer à Cloud Functions. Si la conteneurisation fait désormais partie de votre workflow de développement d'applications, en particulier s'il s'agit d'un pipeline CI/CD (intégration continue/livraison ou déploiement continus), envisagez de migrer vers Cloud Run. Ces scénarios sont couverts par les modules suivants :
- Migrer d'App Engine vers Cloud Functions : consultez le module 11.
- Migrer d'App Engine vers Cloud Run : consultez le module 4 pour conteneuriser votre application avec Docker, ou le module 5 pour le faire sans conteneurs, sans connaissances sur Docker ni
Dockerfile.
Le passage à une autre plate-forme serverless est facultatif. Nous vous recommandons d'examiner les meilleures options pour vos applications et vos cas d'utilisation avant d'apporter des modifications.
Quel que soit le module de migration que vous envisagez ensuite, vous pouvez accéder à l'ensemble du contenu Serverless Migration Station (ateliers de programmation, vidéos, code source [le cas échéant]) dans son dépôt Open Source. Le README du dépôt fournit également des conseils sur les migrations à envisager et sur l'"ordre" pertinent des modules de migration.
7. Ressources supplémentaires
Problèmes/commentaires concernant l'atelier de programmation
Si vous rencontrez des problèmes avec cet atelier de programmation, commencez par faire une recherche avant de les signaler. Liens vers la recherche et la création d'un signalement :
Ressources de migration
Vous trouverez des liens vers les dossiers des dépôts du module 15 (code de départ "START") et du module 16 (code final "FINISH") dans le tableau ci-dessous. Vous pouvez également y accéder depuis le dépôt pour toutes les migrations d'ateliers de programmation App Engine que vous pouvez cloner ou télécharger sous forme de fichier ZIP.
Atelier de programmation | Python 2 | Python 3 |
Module 15 | N/A | |
Module 16 (cet atelier de programmation) | (identique à Python 2) |
Ressources en ligne
Vous trouverez ci-dessous des ressources en ligne qui peuvent être utiles pour ce tutoriel :
Blobstore App Engine et Cloud Storage
- Service Blobstore App Engine
- Migrer vers la bibliothèque cliente Cloud Storage
- Page d'accueil de Cloud Storage
- Documentation Cloud Storage
Plate-forme App Engine
- Documentation App Engine
- Environnement d'exécution Python 2 App Engine (environnement standard)
- Utiliser les bibliothèques intégrées d'App Engine sur Python 2 App Engine
- Environnement d'exécution Python 3 App Engine (environnement standard)
- Différences entre les environnements d'exécution Python 2 et Python 3 App Engine (environnement standard)
- Guide de migration d'App Engine (environnement standard) de Python 2 vers Python 3
- Informations sur les tarifs et les quotas d'App Engine
- Lancement de la plate-forme App Engine de deuxième génération (2018)
- Comparer les plates-formes de première et de deuxième génération
- Compatibilité à long terme avec les anciens environnements d'exécution
- Dépôt d'exemples de migration de la documentation
- Dépôt d'exemples de migration issus de la communauté
Informations sur les autres clouds
- Python sur Google Cloud Platform
- Bibliothèques clientes Google Cloud Python
- Niveau "Toujours sans frais" de Google Cloud
- SDK Google Cloud (outil de ligne de commande
gcloud) - Toute la documentation Google Cloud
Python
- Systèmes de création de modèles Django et Jinja2
webapp2framework Web- Documentation sur
webapp2 - Liens
webapp2_extras - Documentation
webapp2_extrasJinja2 - Framework Web Flask
Vidéos
- Serverless Migration Station
- Expéditions sans serveur
- S'abonner à Google Cloud Tech
- S'abonner à Google Developers
Licence
Ce document est publié sous une licence Creative Commons Attribution 2.0 Generic.