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 sur la station de migration sans serveur (tutoriels pratiques et d'auto-formation) et les vidéos associées visent à aider les développeurs sans serveur Google Cloud à moderniser leurs applications en les guidant dans une ou plusieurs migrations, principalement en abandonnant les anciens services. Vous améliorez ainsi la portabilité de vos applications, et vous bénéficiez de plus d'options et de flexibilité. Vous pouvez ainsi intégrer un plus large éventail de produits Cloud et y accéder, et passer plus facilement à de nouvelles langues. Bien qu'elle s'adresse initialement aux utilisateurs les plus anciens du cloud, principalement les développeurs d'environnements App Engine (standard), cette série est suffisamment large pour inclure d'autres plates-formes sans serveur telles que Cloud Functions et Cloud Run, ou ailleurs, le cas échéant.

Cet atelier de programmation vous explique comment utiliser les tâches d'envoi de la file d'attente de tâches App Engine dans l'application exemple de l'atelier de programmation du module 1. L'article de blog et la vidéo du module 7 complètent ce tutoriel et en donnent une brève présentation.

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. Ceux qui utilisent des files d'attente pour les tâches d'extraction migreront vers Cloud Pub/Sub et doivent plutôt se référer aux modules 18 à 19.

Vous apprendrez à

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

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 ?

<ph type="x-smartling-placeholder"></ph> Débutant Intermédiaire Expert
.

2. Contexte

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 des anciens services groupés tels que Task Queue vers d'autres services cloud autonomes ou équivalents.

La migration des tâches pull est abordée dans les modules 18 à 19 de migration, tandis que les modules 7 à 9 sont consacrés à la migration des tâches d'envoi. Pour migrer des tâches d'envoi de la file d'attente de tâches App Engine, ajoutez son utilisation à l'application Flask et App Engine NDB existante issue 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 de l'utilisateur. Étant donné que les visites plus anciennes ne sont plus jamais affichées et occupent de l'espace dans Datastore, nous allons créer une tâche d'envoi pour supprimer automatiquement les visites les plus anciennes. Dans la suite du module 8, nous migrerons cette application de la file d'attente de tâches vers Cloud Tasks.

Ce tutoriel comprend les étapes suivantes:

  1. Configuration/Préparation
  2. Mettre à jour la configuration
  3. Modifier le code d'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 permettent de s'assurer que vous commencez avec du 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 opérationnelle du module 1: suivez l'atelier de programmation du module 1 (recommandé) ou copiez l'application du module 1 à partir du dépôt. Que vous utilisiez le vôtre ou le nôtre, c'est dans le code du module 1 que nous allons "COMMENCER". Cet atelier de programmation présente chaque étape, se terminant par un code semblable à celui du dossier du dépôt du module 7 "FINISH".

Quelle que soit l'application du module 1 que vous utilisez, le dossier doit se présenter comme suit, éventuellement avec un dossier lib:

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

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

Exécutez les étapes suivantes pour (re)déployer l'application du module 1:

  1. Supprimez le dossier lib s'il y en a un, puis exécutez pip install -t lib -r requirements.txt pour remplir à nouveau lib. Si Python 2 et 3 sont installés, vous devrez peut-être utiliser la commande pip2 à la place.
  2. Assurez-vous d'avoir installé et initialisé l'outil de ligne de commande gcloud, et vérifié son utilisation.
  3. Définissez votre projet Cloud avec gcloud config set project PROJECT_ID si vous ne souhaitez pas saisir votre PROJECT_ID avec chaque commande gcloud émise.
  4. Déployer l'exemple d'application avec gcloud app deploy
  5. Vérifier que l'application du module 1 fonctionne comme prévu sans que les visites les plus récentes ne s'affichent (voir 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 principal de l'application est main.py. Toutes les mises à jour de cette section concernent ce fichier. Une mise à jour mineure a également été apportée au modèle Web, templates/index.html. Voici les modifications à implémenter dans cette section:

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

1. Mettre à jour les importations

L'importation de google.appengine.api.taskqueue apporte la fonctionnalité de file d'attente de tâches. Certains packages de bibliothèques standards Python sont également requis:

  • Étant donné que nous ajoutons une tâche pour supprimer les visites les plus anciennes, l'application devra traiter les codes temporels, c'est-à-dire l'utilisation de time et datetime.
  • Pour consigner des informations utiles concernant l'exécution des tâches, nous avons besoin de logging.

Si vous ajoutez toutes ces importations, voici à quoi ressemble votre code 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 d'envoi (organiser les données pour la tâche, mettre la nouvelle tâche en file d'attente)

La documentation de la file d'attente d'envoi indique : "Pour traiter une tâche, vous devez l'ajouter à une file d'attente d'envoi. App Engine fournit 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 toutes 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 en savoir plus sur la définition de vos propres files d'attente d'envoi, avec des caractéristiques identiques ou différentes, consultez la documentation Créer des files d'attente d'envoi.

L'objectif principal de cet atelier de programmation est d'ajouter une tâche (à la file d'attente d'envoi default) dont la tâche consiste à supprimer les anciennes visites de Datastore qui ne sont plus affichées. L'application de référence enregistre chaque visite (requête GET envoyée à /) en créant une entité Visit, puis extrait et affiche les visites les plus récentes. Aucune des visites les plus anciennes ne sera jamais affichée ni utilisée à nouveau. Par conséquent, la tâche d'envoi supprime toutes les visites antérieures aux plus anciennes. Pour ce faire, le comportement de l'application doit changer légèrement:

  1. Lorsque vous interrogez les visites les plus récentes, au lieu de les renvoyer immédiatement, modifiez l'application de manière à enregistrer le code temporel du dernier Visit, le plus ancien affiché. Vous pouvez supprimer toutes les visites antérieures à celle-ci en toute sécurité.
  2. Créez une tâche d'envoi avec cet horodatage 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 nombre flottant) à la tâche, mais également le consigner (sous forme de chaîne) et renvoyer cette chaîne en tant que valeur sentinelle à afficher à l'utilisateur.

Tout se passe dans fetch_visits(), et voici ce à quoi cela ressemble avant et après ces mises à jour:

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)

Même si la suppression des anciennes visites aurait pu être effectuée facilement dans fetch_visits(), notez 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 profitera de l'accélération des requêtes, car il y aura moins d'informations dans Datastore. Créez une fonction trim(), appelée via une requête POST de file d'attente de tâches vers /trim, qui effectue les opérations suivantes:

  1. Extrait la "visite la plus ancienne" charge utile de code temporel
  2. Émet une requête Datastore pour rechercher toutes les entités antérieures à cet horodatage.
  3. Opte pour une clé "keys-only" plus rapide car aucune donnée utilisateur réelle n'est nécessaire.
  4. Consigne le nombre d'entités à supprimer (y compris zéro).
  5. Appel de ndb.delete_multi() pour supprimer des entités (ignoré dans le cas contraire)
  6. Renvoie une chaîne vide (ainsi qu'un code de retour HTTP 200 implicite).

Vous pouvez voir tout cela 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 le 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 l'extrait de code ci-dessous après la liste des visites affichée, mais avant de fermer le corps du message. Votre modèle se présentera ainsi comme suit:

<!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, en vérifiant qu'elle fonctionne comme prévu et dans tout résultat réfléchi. Après la validation de l'application, effectuez un nettoyage 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 devrait maintenant correspondre à ce qui se trouve dans le dossier du dépôt du module 7. Il est maintenant prêt pour la migration vers Cloud Tasks dans le module 8.

Effectuer un nettoyage

Général

Si vous avez terminé, nous vous recommandons de désactiver votre application App Engine afin d'éviter que des frais ne vous soient facturés. Toutefois, si vous souhaitez effectuer d'autres tests, la plate-forme App Engine dispose d'un quota sans frais. Tant que vous ne dépassez pas ce niveau d'utilisation, aucuns frais ne vous seront facturés. Cela concerne le calcul, mais des frais peuvent également s'appliquer pour les services App Engine concernés. Pour en savoir plus, consultez sa page des tarifs. 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 "Informations spécifiques à cet atelier de programmation" ci-dessous.

Afin d'informer l'ensemble des utilisateurs, le déploiement sur une plate-forme de calcul sans serveur Google Cloud comme App Engine entraîne des coûts minimes de compilation et de stockage. Cloud Build et Cloud Storage disposent de leur propre quota sans frais. Le stockage de cette image utilise une partie de ce quota. Cependant, vous pouvez résider dans une région qui n'offre pas ce type de version sans frais. Vous devez donc surveiller l'utilisation de votre espace de stockage afin de réduire les coûts potentiels. "Dossiers" Cloud Storage spécifiques 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 comptez pas utiliser cette application ou d'autres ateliers de programmation liés à la migration, 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

Dans cette "migration", vous avez ajouté l'utilisation des files d'attente d'envoi de la file d'attente de tâches à l'application exemple du module 1, en ajoutant la prise en charge du suivi des visiteurs, ce qui vous a permis d'obtenir l'application exemple du module 7. La migration suivante vous explique comment passer des tâches de transfert 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. Vous trouverez plus d'informations à ce sujet dans la section suivante.

Si vous voulez passer à Cloud Tasks, vous devez suivre l'atelier de programmation du module 8. Il existe également d'autres migrations à envisager, telles que Cloud Datastore, Cloud Memorystore, Cloud Storage ou Cloud Pub/Sub (files d'attente de retrait). Il existe également des migrations de produits vers Cloud Run et Cloud Functions. Tout le contenu de la station de migration sans serveur (ateliers de programmation, vidéos, code source [si disponible]) est accessible dans son dépôt Open Source.

7. Migration vers Python 3

À l'automne 2021, l'équipe App Engine a étendu la prise en charge de nombreux services groupés aux environnements d'exécution de 2e génération (uniquement disponibles à l'origine dans les environnements d'exécution de 1re génération), ce qui 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 le cloud autonome ou des équivalents tiers comme Cloud Tasks lors du portage de votre application vers Python 3. En d'autres termes, vous pouvez continuer à utiliser la file d'attente de tâches dans les applications App Engine Python 3 tant que vous modifiez le code pour accéder aux services groupés à partir d'environnements d'exécution 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 soit hors du champ d'application du module 7, vous trouverez ci-dessous les versions Python 3 des applications des modules 1 et 7 portées vers Python 3, qui utilisent toujours App Engine NDB et la file d'attente de tâches.

8. Ressources supplémentaires

Vous trouverez ci-dessous des ressources supplémentaires destinées aux développeurs qui étudient plus en détail ce module de migration ou le module de migration associé, ainsi que les produits associés. Vous y trouverez, par exemple, des emplacements où vous pouvez envoyer des commentaires sur ce contenu, des liens vers le code et diverses documents susceptibles de vous être utiles.

Commentaires et problèmes concernant les ateliers 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 de dépôt des 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 vous être utiles pour ce tutoriel:

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

Plate-forme App Engine

Autres informations sur le cloud

Vidéos

Licence

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