Module 3: Migrer de Google Cloud NDB vers Cloud Datastore

1. Présentation

Cette suite d'ateliers de programmation (tutoriels pratiques à suivre à votre rythme) est destinée à aider les développeurs Google App Engine (environnement standard) à moderniser leurs applications en les guidant tout au long d'une série de migrations. L'étape la plus importante est de délaisser les services groupés de l'environnement d'exécution d'origine, car les environnements d'exécution nouvelle génération sont plus souples et offrent aux utilisateurs davantage d'options de service. Le passage à l'environnement d'exécution nouvelle génération vous permet d'intégrer plus facilement les produits Google Cloud, d'utiliser une plus large gamme de services compatibles et de prendre en charge les versions de langage actuelles.

Ce tutoriel facultatif explique aux développeurs comment migrer de Cloud NDB vers Cloud Datastore en tant que bibliothèque cliente pour communiquer avec le service Datastore. Les développeurs qui préfèrent NDB peuvent continuer à l'utiliser, car il est compatible avec Python 3. C'est pourquoi cette migration est facultative. Cette migration n'est destinée qu'à ceux qui souhaitent créer une base de code cohérente et des bibliothèques partagées avec d'autres applications utilisant déjà Cloud Datastore. Cela est expliqué dans la section "Contexte".

Vous apprendrez à effectuer les tâches suivantes :

  • Utiliser Cloud NDB (si vous ne le connaissez pas déjà)
  • Migrer de Cloud NDB vers Cloud Datastore
  • Migrer votre application vers Python 3

Prérequis

  • Un projet Google Cloud Platform avec un compte de facturation GCP actif
  • Des connaissances de base en Python
  • Bonne connaissance des commandes Linux de base
  • Des connaissances de base sur le développement et le déploiement d'applications App Engine
  • Une application 2.x ou 3.x du module 2 App Engine fonctionnelle.

Enquête

Comment allez-vous utiliser cet atelier de programmation ?

Je vais le lire uniquement Je vais le lire et effectuer les exercices

2. Arrière-plan

Bien que Cloud NDB soit une excellente solution Datastore pour les développeurs App Engine de longue date et qu'elle facilite la transition vers Python 3, ce n'est pas la seule façon pour les développeurs App Engine d'accéder à Datastore. Lorsque Datastore d'App Engine est devenu un produit à part entière en 2013, Google Cloud Datastore, une nouvelle bibliothèque cliente a été créée pour que tous les utilisateurs puissent utiliser Datastore.

Les développeurs Python 3 App Engine et non-App Engine sont invités à utiliser Cloud Datastore (et non Cloud NDB). Nous encourageons les développeurs Python 2 App Engine à migrer de ndb vers Cloud NDB, puis à transférer vers Python 3. Ils peuvent également choisir de migrer vers Cloud Datastore. Il s'agit d'une décision logique, en particulier pour les développeurs qui disposent déjà de code utilisant Cloud Datastore, comme ceux mentionnés ci-dessus, et qui souhaitent créer des bibliothèques partagées pour toutes leurs applications. La réutilisation du code est une bonne pratique, tout comme la cohérence du code. Les deux contribuent à réduire le coût de maintenance global, comme indiqué ci-dessous :

Migration de Cloud NDB vers Cloud Datastore

  • Permet aux développeurs de se concentrer sur un seul codebase pour l'accès à Datastore
  • Évite de gérer du code avec Cloud NDB et d'autres avec Cloud Datastore
  • Assure une meilleure cohérence dans le codebase et une meilleure réutilisabilité du code
  • Permet d'utiliser des bibliothèques communes/partagées, ce qui contribue à réduire le coût global de maintenance

La migration comprend les étapes principales suivantes :

  1. Configuration/Préparation
  2. Remplacer Cloud NDB par les bibliothèques clientes Cloud Datastore
  3. Mettre à jour l'application

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 terminé l'atelier de programmation du module 2, 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 que App Engine (app) est activé.

2. Obtenir un exemple d'application de référence

L'une des conditions préalables est de disposer de l'exemple d'application du module 2. Vous pouvez utiliser votre propre application si vous avez suivi ce tutoriel. Sinon, vous pouvez suivre le tutoriel maintenant (lien ci-dessus) ou simplement copier le dépôt du module 2 (lien ci-dessous).

Que vous utilisiez votre application ou la nôtre, le code de départ ("START") est celui du module 2. Le présent atelier de programmation du module 3 vous guide pour chaque étape jusqu'à obtenir un code similaire au code final ("FINISH"). Il existe des versions Python 2 et 3 de ce tutoriel. Choisissez le dépôt de code approprié ci-dessous.

Python 2

Pour Python 2, le répertoire de départ (votre code ou notre code) doit ressembler à ce qui suit :

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

Si vous avez suivi le tutoriel du module 2, vous avez également un dossier lib avec Flask et ses dépendances. Si vous n'avez pas de dossier lib, créez-le à l'aide de la commande pip install -t lib -r requirements.txt afin que nous puissions déployer cette application de référence à l'étape suivante. Si Python 2 et Python 3 sont tous les deux installés, nous vous recommandons d'utiliser pip2 plutôt que pip afin d'éviter toute confusion avec Python 3.

Python 3

Pour Python 3, le répertoire de départ (votre code ou notre code) doit ressembler à ce qui suit :

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

Ni lib, ni appengine_config.py ne sont utilisés pour Python 3.

3. (Re)Déployer l'application du module 2

Étapes préliminaires restantes :

  1. Familiarisez-vous avec l'outil de ligne de commande gcloud (si nécessaire).
  2. (Re)déployez le code du module 1 sur App Engine (si nécessaire).

Une fois que vous avez exécuté ces étapes et vérifié le bon fonctionnement du code, nous pouvons passer à la suite de ce tutoriel en commençant par les fichiers de configuration.

4. Remplacer Cloud NDB par les bibliothèques clientes Cloud Datastore

La seule modification de configuration consiste à remplacer un package mineur dans votre fichier requirements.txt.

1. Mettre à jour requirements.txt

À la fin du module 2, votre fichier requirements.txt se présentait comme suit :

  • AVANT (Python 2 et 3) :
Flask==1.1.2
google-cloud-ndb==1.7.1

Mettez à jour requirements.txt en remplaçant la bibliothèque Cloud NDB (google-cloud-ndb) par la dernière version de la bibliothèque Cloud Datastore (google-cloud-datastore), en laissant l'entrée pour Flask intacte, en gardant à l'esprit que la dernière version de Cloud Datastore compatible avec Python 2 est la version 1.15.3 :

  • APRÈS (Python 2) :
Flask==1.1.2
google-cloud-datastore==1.15.3
  • APRÈS (Python 3) :
Flask==1.1.2
google-cloud-datastore==2.1.0

N'oubliez pas que le dépôt est mis à jour plus régulièrement que ce tutoriel. Il est donc possible que le fichier requirements.txt reflète des versions plus récentes. Nous vous recommandons d'utiliser les dernières versions de chaque bibliothèque. Toutefois, si celles-ci ne fonctionnent pas, vous pouvez rétablir une version antérieure. Les numéros de version ci-dessus sont les derniers disponibles lors de la dernière mise à jour de cet atelier de programmation.

2. Autres fichiers de configuration

Les autres fichiers de configuration, app.yaml et appengine_config.py, doivent rester inchangés par rapport à l'étape de migration précédente :

  • app.yaml doit (toujours) faire référence aux packages tiers groupés grpcio et setuptools.
  • appengine_config.py doit (toujours) pointer pkg_resources et google.appengine.ext.vendor vers les ressources tierces dans lib.

Passons maintenant aux fichiers d'application.

5. Mettre à jour les fichiers de l'application

Aucune modification n'a été apportée à template/index.html, mais quelques mises à jour concernent main.py.

1. Importations

Le code de démarrage de la section d'importation doit se présenter comme suit :

  • AVANT :
from flask import Flask, render_template, request
from google.cloud import ndb

Remplacez l'importation google.cloud.ndb par celle de Cloud Datastore : google.cloud.datastore. Étant donné que la bibliothèque cliente Datastore n'est pas compatible avec la création automatique d'un champ d'horodatage dans une entité, importez également le module de bibliothèque standard datetime pour en créer un manuellement. Par convention, les importations de bibliothèques standards sont placées au-dessus des importations de packages tiers. Une fois ces modifications apportées, le code doit se présenter comme suit :

  • APRÈS :
from datetime import datetime
from flask import Flask, render_template, request
from google.cloud import datastore

2. Initialisation et modèle de données

Après l'initialisation de Flask, l'exemple d'application du module 2 qui crée une classe de modèle de données NDB et ses champs se présente comme suit :

  • AVANT :
app = Flask(__name__)
ds_client = ndb.Client()

class Visit(ndb.Model):
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)

La bibliothèque Cloud Datastore ne comporte pas de classe de ce type. Supprimez donc la déclaration de la classe Visit. Vous avez toujours besoin d'un client pour communiquer avec Datastore. Remplacez donc ndb.Client() par datastore.Client(). La bibliothèque Datastore est plus "flexible" et vous permet de créer des entités sans "prédéclarer" leur structure comme NDB. Après cette mise à jour, cette partie de main.py devrait se présenter comme suit :

  • APRÈS :
app = Flask(__name__)
ds_client = datastore.Client()

3. Accès à Datastore

La migration vers Cloud Datastore nécessite de modifier la façon dont vous créez, stockez et interrogez les entités Datastore (au niveau utilisateur). Pour vos applications, la difficulté de cette migration dépend de la complexité de votre code Datastore. Dans notre exemple d'application, nous avons essayé de rendre la mise à jour aussi simple que possible. Voici notre code de départ :

  • AVANT :
def store_visit(remote_addr, user_agent):
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

def fetch_visits(limit):
    with ds_client.context():
        return (v.to_dict() for v in Visit.query().order(
                -Visit.timestamp).fetch_page(limit)[0])

Avec Cloud Datastore, créez une entité générique en identifiant les objets groupés dans votre entité avec une "clé". Créez l'enregistrement de données avec un objet JSON (Python dict) de paires clé/valeur, puis écrivez-le dans Datastore avec le put() attendu. L'interrogation est similaire, mais plus simple avec Datastore. Vous pouvez voir ici en quoi le code Datastore équivalent diffère :

  • APRÈS :
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)

Mettez à jour les corps de fonction pour store_visit() et fetch_visits() comme ci-dessus, en conservant des signatures identiques à la version précédente. Aucune modification n'a été apportée au gestionnaire principal root(). Une fois ces modifications effectuées, votre application est désormais équipée pour utiliser Cloud Datastore et est prête à être testée.

6. Résumé/Nettoyage

Déployer l'application

Redéployez votre application avec gcloud app deploy et confirmez qu'elle fonctionne correctement. Votre code doit maintenant correspondre à celui des dossiers du dépôt du module 3 :

Si vous avez consulté cette série sans suivre les ateliers de programmation précédents, l'application elle-même ne change pas. Elle enregistre toutes les visites sur la page Web principale (/) et ressemble à ceci une fois que vous avez consulté le site suffisamment de fois :

Application Visitme

Bravo ! Vous avez terminé l'atelier de programmation du module 3. Vous savez maintenant que vous pouvez utiliser les bibliothèques clientes Cloud NDB et Cloud Datastore pour accéder à Datastore. En migrant vers cette dernière, vous pouvez désormais bénéficier des avantages des bibliothèques partagées, du code commun et de la réutilisation du code pour assurer la cohérence et réduire les coûts de maintenance.

Facultatif : Effectuer un nettoyage

Que diriez-vous d'un bon nettoyage pour éviter que des frais vous soient facturés tant que vous n'êtes pas prêt à passer à l'atelier de programmation suivant sur la migration ? En tant que développeur existant, vous connaissez probablement déjà les informations de tarification d'App Engine.

Facultatif : Désactiver l'application

Si vous n'êtes pas encore prêt à passer au tutoriel suivant, désactivez votre application pour éviter les frais. Lorsque vous serez prêt à passer au prochain atelier de programmation, vous pourrez le réactiver. Tant que votre application est désactivée, elle ne génère aucun trafic, donc aucuns frais. Toutefois, si vous dépassez le quota sans frais, votre utilisation de Datastore vous sera facturée. Supprimez donc suffisamment d'éléments pour rester dans la limite.

En revanche, si vous ne souhaitez pas poursuivre vos migrations et souhaitez supprimer tous les éléments, vous pouvez arrêter le projet.

Étapes suivantes

Vous pouvez ensuite explorer les modules de migration suivants :

  • Module 3 : Bonus : passez à la section bonus pour découvrir comment porter votre application vers Python 3 et utiliser l'environnement d'exécution App Engine nouvelle génération.
  • Module 7 : files d'attente d'envoi de tâches App Engine (obligatoire si vous utilisez des files d'attente de tâches d'envoi de tâches [push])
    • Ajoutez des tâches push taskqueue App Engine à l'application du module 1.
    • Préparez les utilisateurs à migrer vers Cloud Tasks dans le module 8.
  • Module 4 : Migrer vers Cloud Run avec Docker
    • Conteneurisez votre application pour l'exécuter sur Cloud Run avec Docker.
    • Cela vous permet de continuer d'utiliser Python 2.
  • Module 5 : Migrer vers Cloud Run avec les packs de création Cloud
    • Conteneurisez votre application pour qu'elle s'exécute sur Cloud Run avec les packs de création Cloud.
    • Il n'est pas nécessaire de déjà connaître Docker, les conteneurs ou les Dockerfile.
    • Vous devez avoir déjà effectué la migration de votre application vers Python 3.
  • Module 6 : Migrer vers Cloud Firestore
    • Migrer vers Cloud Firestore pour utiliser les fonctionnalités de Firebase.
    • Bien que Cloud Firestore soit compatible avec Python 2, cet atelier de programmation n'est disponible que pour Python 3.

7. BONUS : Migrer vers Python 3

Pour bénéficier des nouvelles fonctionnalités et des derniers environnements d'exécution App Engine, nous vous recommandons de migrer vers Python 3. Dans notre exemple d'application, Datastore était le seul service intégré utilisé. La migration de ndb vers Cloud NDB ayant été effectuée, nous pouvons maintenant transitionner vers l'environnement d'exécution Python 3 d'App Engine.

Présentation

Bien que le portage vers Python 3 dépasse le cadre d'un simple tutoriel Google Cloud, la présente partie de notre atelier de programmation donne aux développeurs une idée des spécificités de l'environnement d'exécution App Engine pour Python 3. L'accès à des packages tiers est l'un des principaux avantages de l'environnement d'exécution nouvelle génération. Il n'est plus nécessaire de spécifier des packages intégrés dans app.yaml, ni de copier ou d'importer des bibliothèques non intégrées (elles sont installées de manière implicite car elles figurent dans requirements.txt).

Comme notre exemple est très basique et que Cloud Datastore est compatible avec les deux versions de Python, le portage ne nécessite aucune modification et le code fonctionne aussi bien sous Python 2 que sous Python 3. Dans le cas présent, seules les modifications de configuration suivantes sont requises :

  1. Simplifier app.yaml pour référencer Python 3 et supprimer la référence aux bibliothèques tierces groupées.
  2. Supprimer appengine_config.py et le dossier lib car ils ne sont plus nécessaires.

Les fichiers d'application main.py et templates/index.html restent inchangés.

Mettre à jour requirements.txt

La dernière version de Cloud Datastore compatible avec Python 2 est la version 1.15.3. Mettez à jour requirements.txt avec la dernière version de Python 3 (qui peut être plus récente maintenant). Au moment de la rédaction de ce tutoriel, la dernière version était la 2.1.0. Modifiez donc cette ligne pour qu'elle ressemble à ceci (ou à la dernière version) :

google-cloud-datastore==2.1.0

Simplier app.yaml

AVANT :

La seule réelle modification pour cet exemple d'application est le fait de raccourcir app.yaml. Pour rappel, voici ce que nous avions dans app.yaml à la fin du module 3 :

runtime: python27
threadsafe: yes
api_version: 1

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

libraries:
- name: grpcio
  version: 1.0.0
- name: setuptools
  version: 36.6.0

APRÈS :

Dans Python 3, les instructions threadsafe, api_version et libraries sont toutes obsolètes. Toutes les applications sont supposées être threadsafe et api_version n'est plus utilisé dans Python 3. Comme aucun package tiers intégré n'est préinstallé sur les services App Engine, le service libraries est également obsolète. Pour plus d'informations sur ces modifications, consultez la documentation sur les modifications apportées à app.yaml. Par conséquent, vous devez supprimer ces trois éléments de app.yaml et passer à une version compatible de Python 3 (voir ci-dessous).

Facultatif : Utilisation de la directive handlers

En outre, la directive handlers, qui dirige le trafic vers des applications App Engine spécifiques, a également été abandonnée. Étant donné que l'environnement d'exécution nouvelle génération suppose que les frameworks Web gèrent le routage des applications, tous les "scripts de gestionnaire" doivent être définis sur "auto". En combinant les modifications ci-dessus, vous obtenez ce fichier app.yaml :

runtime: python38

handlers:
- url: /.*
  script: auto

Pour en savoir plus sur script: auto, consultez la page de référence sur app.yaml.

Supprimer l'instruction handlers

Étant donné que handlers est obsolète, vous pouvez également supprimer toute la section et ne laisser qu'une seule ligne dans votre fichier app.yaml :

runtime: python38

Par défaut, le serveur Web WSGI Gunicorn est disponible pour toutes les applications. Si vous maîtrisez gunicorn, voici la commande qui s'exécute lors d'un démarrage par défaut avec un fichier app.yaml réduit au strict minimum :

gunicorn main:app --workers 2 -c /config/gunicorn.py

Facultatif : Utilisation de la directive entrypoint

Toutefois, vous pouvez utiliser une instruction entrypoint si votre application nécessite une commande de démarrage spécifique, auquel cas votre fichier app.yaml ressemble à ceci :

runtime: python38
entrypoint: python main.py

Cet exemple demande spécifiquement un serveur de développement Flask plutôt que d'utiliser gunicorn. Le code qui démarre le serveur de développement doit également être ajouté à votre application pour démarrer sur l'interface 0.0.0.0 sur le port 8080 en ajoutant cette petite section à la fin de main.py :

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)

Pour en savoir plus sur entrypoint, consultez la page de référence sur app.yaml. Pour obtenir d'autres exemples et bonnes pratiques, consultez la documentation sur le démarrage de l'environnement standard App Engine ainsi que la documentation sur le démarrage de l'environnement flexible App Engine.

Supprimer appengine_config.py et lib

Supprimez le fichier appengine_config.py et le dossier lib. Lors de la migration vers Python 3, App Engine acquiert et installe les packages répertoriés dans requirements.txt.

Le fichier de configuration appengine_config.py permet de reconnaître les bibliothèques et packages tiers, que vous les ayez copiés vous-même ou que vous utilisiez ceux qui sont déjà disponibles sur des serveurs App Engine (intégrés) Voici un résumé des principaux changements lorsque vous passez à Python 3 :

  1. Pas de regroupement de bibliothèques tierces copiées (répertoriées dans requirements.txt).
  2. Pas de pip install dans un dossier lib et pas de dossier lib.
  3. Pas de liste de bibliothèques tierces dans app.yaml.
  4. Pas besoin de référencer une application auprès des bibliothèques tierces, et donc pas de fichier appengine_config.py.

Il vous suffit de répertorier toutes les bibliothèques tierces requises dans requirements.txt.

Déployer l'application

Redéployez votre application pour vous assurer qu'elle fonctionne. Vous pouvez également vérifier que votre solution est identique à l'exemple de code Python 3 du module 3. Pour visualiser les différences avec Python 2, comparez le code à sa version Python 2.

Nous vous félicitons d'avoir terminé l'étape bonus du module 3 ! Consultez la documentation sur la préparation des fichiers de configuration pour l'environnement d'exécution Python 3. Enfin, consultez le récapitulatif ci-dessus pour connaître les étapes suivantes et effectuer un nettoyage.

Préparer votre application

Au moment de procéder à la migration de votre application, vous devez transférer le fichier main.py et les autres fichiers de l'application vers la version 3.x. Il est donc recommandé d'optimiser autant que possible la compatibilité ascendante de votre application 2.x.

Pour ce faire il existe de nombreuses ressources en ligne mais voici quelques conseils essentiels :

  1. Assurez-vous que toutes les dépendances de votre application sont entièrement compatibles avec la version 3.x.
  2. Assurez-vous que votre application s'exécute au moins avec la version 2.6 (de préférence 2.7).
  3. Assurez-vous que l'application réussit en intégralité la suite de tests (avec une couverture minimale de 80 %).
  4. Utilisez des bibliothèques de compatibilité telles que six, Future et/ou Modernize.
  5. Informez-vous sur les principaux problèmes de compatibilité entre les versions 2.x et 3.x.
  6. Toute E/S peut entraîner des incompatibilités entre les chaînes Unicode et les chaînes d'octets.

L'exemple d'application a été conçu pour tenir compte de tous ces aspects, ce qui explique pourquoi l'application s'exécute aussi bien sous 2.x que sous 3.x. Nous pouvons donc nous concentrer sur les modifications à apporter pour utiliser la plate-forme nouvelle génération.

8. Ressources supplémentaires

Problèmes/commentaires concernant le module de migration App Engine en 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 dans le tableau ci-dessous des liens vers les dossiers de dépôt correspondant au module 2 ("START") et au module 3 ("FINISH"). Vous pouvez également y accéder depuis le dépôt pour toutes les migrations App Engine que vous pouvez cloner ou télécharger sous forme de fichier ZIP.

Atelier de programmation

Python 2

Python 3

Module 2

code

code

Module 3

code

code

Ressources App Engine

Vous trouverez ci-dessous d'autres ressources concernant cette migration spécifique :