Utiliser la file d'attente de tâches App Engine (tâches d'envoi) dans les applications Flask (module 7)

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 utiliser les tâches push App Engine Task Queue dans l'exemple d'application de l'atelier de programmation du module 1. L'article de blog et la vidéo du module 7 complètent ce tutoriel en fournissant une brève présentation de son contenu.

Dans ce module, nous allons ajouter l'utilisation des tâches push, puis migrer cette utilisation vers Cloud Tasks dans le module 8, puis vers Python 3 et Cloud Datastore dans le module 9. Les utilisateurs de Task Queues pour les tâches de retrait migreront vers Cloud Pub/Sub et devront se reporter aux modules 18 et 19.

Vous apprendrez à

  • Utiliser l'API/le service groupé de file d'attente des tâches App Engine
  • Ajouter l'utilisation des tâches push à une application Python 2 Flask App Engine NDB de base

Prérequis

Enquête

Comment allez-vous utiliser ce tutoriel ?

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

Quel est votre niveau d'expérience avec Python ?

Débutant Intermédiaire Expert

Quel est votre niveau d'expérience avec les services Google Cloud ?

Débutant Intermédiaire Expert

2. Arrière-plan

La file d'attente de tâches App Engine accepte les tâches d'envoi et de retrait. Pour améliorer la portabilité des applications, l'équipe Google Cloud recommande de migrer les anciens services groupés tels que Task Queue vers d'autres services Cloud autonomes ou équivalents tiers.

La migration des tâches pull est abordée dans les modules 18 et 19, tandis que les modules 7 à 9 se concentrent sur la migration des tâches push. Pour migrer des tâches push App Engine Task Queue, ajoutez leur utilisation à l'application Flask et App Engine NDB existante résultant de l'atelier de programmation du module 1. Dans cette application, une nouvelle page vue enregistre une nouvelle visite et affiche les visites les plus récentes à l'utilisateur. Étant donné que les anciennes visites ne sont plus jamais affichées et qu'elles occupent de l'espace dans Datastore, nous allons créer une tâche push pour supprimer automatiquement les visites les plus anciennes. Dans le module 8, nous migrerons cette application de Task Queue vers Cloud Tasks.

Ce tutoriel comprend les étapes suivantes :

  1. Configuration/Préparation
  2. Mettre à jour la configuration
  3. Modifier le code de l'application

3. Configuration/Préparation

Cette section explique comment effectuer les opérations suivantes :

  1. Configurer votre projet Cloud
  2. Obtenir un exemple d'application de référence
  3. (Re)Déployer et valider l'application de référence

Ces étapes vous permettent de commencer avec un code fonctionnel.

1. Configurer le projet

Si vous avez terminé l'atelier de programmation du module 1, 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'une application App Engine fonctionnelle du module 1. Pour cela, suivez l'atelier de programmation du module 1 (recommandé) ou copiez l'application du module 1 depuis le dépôt. Que vous utilisiez votre application ou la nôtre, le code de départ ("START") est celui du module 1. Cet atelier de programmation vous guide pour chaque étape jusqu'à obtenir un code similaire à celui du dossier "FINISH" du dépôt du module 7.

Quelle que soit l'application du module 1 que vous utilisez, le dossier doit ressembler à ce qui suit, avec éventuellement un dossier lib :

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

3. (Re)Déployer l'application de référence

Pour (re)déployer l'application du module 1, procédez comme suit :

  1. Supprimez le dossier lib s'il existe, puis exécutez pip install -t lib -r requirements.txt pour le remplir à nouveau.lib Si vous avez installé Python 2 et Python 3, vous devrez peut-être utiliser la commande pip2.
  2. Assurez-vous d'avoir installé et initialisé l'outil de ligne de commande gcloud, et d'avoir consulté son utilisation.
  3. Définissez votre projet Cloud avec gcloud config set project PROJECT_ID si vous ne souhaitez pas saisir votre PROJECT_ID à chaque commande gcloud émise.
  4. Déployez l'exemple d'application avec gcloud app deploy
  5. Vérifiez que l'application du module 1 s'exécute comme prévu, sans problème, et qu'elle affiche les visites les plus récentes (comme illustré ci-dessous).

a7a9d2b80d706a2b.png

4. Mettre à jour la configuration

Aucune modification n'est nécessaire dans les fichiers de configuration App Engine standards (app.yaml, requirements.txt, appengine_config.py).

5. Modifier les fichiers d'application

Le fichier d'application principal est main.py. Toutes les mises à jour de cette section concernent ce fichier. Une mise à jour mineure du modèle Web, templates/index.html, est également disponible. Voici les modifications à implémenter dans cette section :

  1. Mettre à jour les importations
  2. Ajouter une tâche push
  3. Ajouter un gestionnaire de tâches
  4. Mettre à jour un modèle Web

1. Mettre à jour les importations

L'importation de google.appengine.api.taskqueue permet d'intégrer la fonctionnalité Task Queue. Certains packages de la bibliothèque standard Python sont également requis :

  • Comme nous ajoutons une tâche pour supprimer les visites les plus anciennes, l'application devra gérer les codes temporels, ce qui signifie utiliser time et datetime.
  • Pour enregistrer des informations utiles sur l'exécution des tâches, nous avons besoin de logging.

En ajoutant toutes ces importations, votre code se présente comme suit avant et après ces modifications :

AVANT :

from flask import Flask, render_template, request
from google.appengine.ext import ndb

APRÈS :

from datetime import datetime
import logging
import time
from flask import Flask, render_template, request
from google.appengine.api import taskqueue
from google.appengine.ext import ndb

2. Ajouter une tâche push (rassembler les données pour la tâche, mettre en file d'attente une nouvelle tâche)

La documentation sur les files d'attente push indique : "Pour traiter une tâche, vous devez l'ajouter à une file d'attente push. App Engine propose une file d'attente d'envoi par défaut, nommée default, qui est configurée et prête à être utilisée avec les paramètres par défaut. Si vous le souhaitez, vous pouvez simplement ajouter l'ensemble de vos tâches à la file d'attente par défaut, sans avoir à créer ni configurer d'autres files d'attente." Cet atelier de programmation utilise la file d'attente default par souci de concision. Pour savoir comment définir vos propres files d'attente push, avec des caractéristiques identiques ou différentes, consultez la documentation sur la création de files d'attente push.

L'objectif principal de cet atelier de programmation est d'ajouter une tâche (à la file d'attente push default) dont le rôle est de supprimer les anciennes visites de Datastore qui ne sont plus affichées. L'application de référence enregistre chaque visite (requête GET vers /) en créant une entité Visit, puis récupère et affiche les visites les plus récentes. Aucune des visites les plus anciennes ne sera plus jamais affichée ni utilisée. La tâche push supprime donc toutes les visites antérieures à la plus ancienne affichée. Pour ce faire, le comportement de l'application doit être légèrement modifié :

  1. Lorsque vous interrogez les visites les plus récentes, au lieu de renvoyer ces visites immédiatement, modifiez l'application pour enregistrer le code temporel du dernier Visit, le plus ancien affiché. Vous pouvez supprimer toutes les visites antérieures à celui-ci.
  2. Créez une tâche push avec ce code temporel comme charge utile et dirigez-la vers le gestionnaire de tâches, accessible via un POST HTTP vers /trim. Plus précisément, utilisez les utilitaires Python standards pour convertir le code temporel Datastore et l'envoyer (sous forme de float) à la tâche, mais aussi pour l'enregistrer (sous forme de chaîne) et renvoyer cette chaîne en tant que valeur sentinelle à afficher à l'utilisateur.

Tout cela se passe dans fetch_visits(). Voici à quoi cela ressemble avant et après avoir apporté ces modifications :

AVANT :

def fetch_visits(limit):
    return (v.to_dict() for v in Visit.query().order(
            -Visit.timestamp).fetch(limit))

APRÈS :

def fetch_visits(limit):
    'get most recent visits and add task to delete older visits'
    data = Visit.query().order(-Visit.timestamp).fetch(limit)
    oldest = time.mktime(data[-1].timestamp.timetuple())
    oldest_str = time.ctime(oldest)
    logging.info('Delete entities older than %s' % oldest_str)
    taskqueue.add(url='/trim', params={'oldest': oldest})
    return (v.to_dict() for v in data), oldest_str

3. Ajouter un gestionnaire de tâches (code appelé lors de l'exécution de la tâche)

Bien que la suppression des anciennes visites aurait pu être facilement effectuée dans fetch_visits(), sachez que cette fonctionnalité n'a pas grand-chose à voir avec l'utilisateur final. Il s'agit d'une fonctionnalité auxiliaire qui peut être traitée de manière asynchrone en dehors des requêtes d'application standards. L'utilisateur final bénéficiera de requêtes plus rapides, car il y aura moins d'informations dans Datastore. Créez une fonction trim(), appelée via une requête Task Queue POST à /trim, qui effectue les opérations suivantes :

  1. Extrait la charge utile de l'horodatage de la visite la plus ancienne.
  2. Émet une requête Datastore pour trouver toutes les entités antérieures à ce code temporel.
  3. Opte pour une requête "clés uniquement" plus rapide, car aucune donnée utilisateur réelle n'est nécessaire.
  4. Enregistre le nombre d'entités à supprimer (y compris zéro).
  5. Appels ndb.delete_multi() pour supprimer les entités (ignorés si ce n'est pas le cas).
  6. Renvoie une chaîne vide (ainsi qu'un code de retour HTTP 200 implicite).

Vous pouvez tout voir dans trim() ci-dessous. Ajoutez-le à main.py juste après fetch_visits() :

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

4. Mettre à jour un modèle Web

Mettez à jour le modèle Web, templates/index.html, avec cette condition Jinja2 pour afficher le code temporel le plus ancien si cette variable existe :

{% if oldest is defined %}
    <b>Deleting visits older than:</b> {{ oldest }}</p>
{% endif %}

Ajoutez cet extrait après la liste des visites affichée, mais avant de fermer le corps, afin que votre modèle ressemble à ceci :

<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
<body>

<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
    <li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>

{% if oldest is defined %}
    <b>Deleting visits older than:</b> {{ oldest }}</p>
{% endif %}
</body>
</html>

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 tout nettoyage nécessaire et réfléchissez aux prochaines étapes.

Déployer et vérifier l'application

Déployez l'application avec gcloud app deploy. Le résultat doit être identique à celui de l'application du module 1, à l'exception d'une nouvelle ligne en bas indiquant les visites qui seront supprimées :

4aa8a2cb5f527079.png

Bravo ! Vous avez terminé cet atelier de programmation. Votre code doit maintenant correspondre à celui du dossier du dépôt du module 7. Elle est maintenant prête à migrer vers Cloud Tasks dans le module 8.

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/images
  • console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com
  • Les liens de stockage ci-dessus dépendent de votre PROJECT_ID et 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 :

Étapes suivantes

Lors de cette "migration", vous avez ajouté l'utilisation de la file d'attente push Task Queue à l'exemple d'application du module 1, en ajoutant la prise en charge du suivi des visiteurs, ce qui a donné lieu à l'exemple d'application du module 7. La prochaine migration vous apprendra à passer des tâches push App Engine à Cloud Tasks si vous le souhaitez. Depuis l'automne 2021, les utilisateurs n'ont plus besoin de migrer vers Cloud Tasks lorsqu'ils passent à Python 3. Pour en savoir plus, consultez la section suivante.

Si vous souhaitez passer à Cloud Tasks, l'atelier de programmation du module 8 est la prochaine étape. Au-delà, d'autres migrations sont à envisager, comme Cloud Datastore, Cloud Memorystore, Cloud Storage ou Cloud Pub/Sub (files d'extraction). Il existe également des migrations interproduits vers Cloud Run et Cloud Functions. 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.

7. Migration vers Python 3

À l'automne 2021, l'équipe App Engine a étendu la compatibilité de nombreux services groupés aux environnements d'exécution de deuxième génération (initialement disponibles uniquement dans les environnements d'exécution de première génération). Cela signifie que vous n'avez plus besoin de migrer des services groupés tels que la file d'attente de tâches App Engine vers des équivalents Cloud autonomes ou tiers tels que Cloud Tasks lorsque vous portez votre application vers Python 3. En d'autres termes, vous pouvez continuer à utiliser Task Queue dans les applications Python 3 App Engine à condition de modifier le code pour accéder aux services groupés à partir des environnements d'exécution de nouvelle génération.

Pour en savoir plus sur la migration de l'utilisation des services groupés vers Python 3, consultez l'atelier de programmation du module 17 et la vidéo correspondante. Bien que ce sujet ne soit pas abordé dans le module 7, vous trouverez ci-dessous les versions Python 3 des applications des modules 1 et 7, qui ont été portées vers Python 3 et qui utilisent toujours App Engine NDB et Task Queue.

8. Ressources supplémentaires

Vous trouverez ci-dessous des ressources supplémentaires pour les développeurs qui souhaitent en savoir plus sur ce module de migration ou sur des modules et produits associés. Vous y trouverez des liens vers le code, des informations sur la façon de nous faire part de vos commentaires sur ce contenu et divers éléments de documentation qui pourraient vous être utiles.

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

Le tableau ci-dessous contient des liens vers les dossiers du dépôt pour les modules 2 (START) et 7 (FINISH).

Atelier de programmation

Python 2

Python 3

Module 1

code

code (non présenté dans ce tutoriel)

Module 7 (cet atelier de programmation)

code

code (non présenté dans ce tutoriel)

Ressources en ligne

Vous trouverez ci-dessous des ressources en ligne qui peuvent être utiles pour ce tutoriel :

File d'attente de tâches d'App Engine

Plate-forme App Engine

Informations sur les autres clouds

Vidéos

Licence

Ce document est publié sous une licence Creative Commons Attribution 2.0 Generic.