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

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 inclure et utiliser des tâches d'extraction dans la file d'attente de tâches App Engine dans l'application exemple de l'atelier de programmation du module 1. Nous allons ajouter son utilisation des tâches pull dans ce tutoriel du module 18, puis migrer cette utilisation vers Cloud Pub/Sub dans le module 19. Ceux qui utilisent les files d'attente pour les tâches push migrent vers Cloud Tasks et doivent, à la place, se reporter aux modules 7 à 9.

Vous apprendrez à

  • Utiliser l'API ou le service groupé de la file d'attente de tâches App Engine
  • Ajouter l'utilisation de la file d'attente de retrait à 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

Pour effectuer la migration depuis des tâches d'extraction 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. L'application exemple affiche les dernières visites de l'utilisateur final. Ce n'est pas un problème, mais il est encore plus intéressant d'effectuer également le suivi de vos visiteurs pour savoir qui visite le plus votre site.

Bien qu'il soit possible d'utiliser des tâches d'envoi pour ce nombre de visiteurs, nous souhaitons répartir la responsabilité entre l'application exemple qui est chargée d'enregistrer les visites et de répondre immédiatement aux utilisateurs, et un "nœud de calcul" désigné. dont la tâche consiste à comptabiliser le nombre de visiteurs en dehors du flux de travail requête-réponse normal.

Pour implémenter cette conception, nous ajoutons l'utilisation de files d'attente de retrait à l'application principale, ainsi que la prise en charge de la fonctionnalité de nœud de calcul. Le nœud de calcul peut s'exécuter en tant que processus distinct (comme une instance backend ou du code exécuté sur une VM en permanence), une tâche Cron ou une requête HTTP de ligne de commande de base à l'aide de curl ou wget. Après cette intégration, vous pourrez migrer l'application vers Cloud Pub/Sub dans l'atelier de programmation suivant (module 19).

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, réutilisez ce projet (et ce 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 d'une application App Engine activée. Recherchez l'ID de votre projet, car vous en aurez besoin plusieurs fois dans cet atelier de programmation. Utilisez-le chaque fois que vous rencontrez la variable PROJECT_ID.

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 pour le 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 18 "FINISH".

Quelle que soit l'application du module 1 que vous utilisez, le dossier doit ressembler à la sortie ci-dessous, éventuellement avec un dossier lib:

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

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

Exécutez les étapes suivantes pour 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 et affiche les visites les plus récentes (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). Ajoutez plutôt un nouveau fichier de configuration, queue.yaml, avec le contenu suivant et placez-le dans le même répertoire de premier niveau:

queue:
- name: pullq
  mode: pull

Le fichier queue.yaml spécifie toutes les files d'attente de tâches qui existent pour votre application, à l'exception de la file d'attente [push] default qui est automatiquement créée par App Engine. Dans le cas présent, il n'y en a qu'une, une file d'attente de retrait nommée pullq. App Engine exige que la directive mode soit spécifiée en tant que pull. Dans le cas contraire, une file d'attente d'envoi est créée par défaut. Pour en savoir plus sur la création de files d'attente de retrait, consultez la documentation. Consultez également la page de référence sur queue.yaml pour découvrir d'autres options.

Déployez ce fichier séparément de votre application. Vous utiliserez toujours gcloud app deploy, mais vous fournirez également queue.yaml dans la ligne de commande:

$ gcloud app deploy queue.yaml
Configurations to update:

descriptor:      [/tmp/mod18-gaepull/queue.yaml]
type:            [task queues]
target project:  [my-project]

WARNING: Caution: You are updating queue configuration. This will override any changes performed using 'gcloud tasks'. More details at
https://cloud.google.com/tasks/docs/queue-yaml

Do you want to continue (Y/n)?

Updating config [queue]...⠹WARNING: We are using the App Engine app location (us-central1) as the default location. Please use the "--location" flag if you want to use a different location.
Updating config [queue]...done.

Task queues have been updated.

Visit the Cloud Platform Console Task Queues page to view your queues and cron jobs.
$

5. Modifier le code d'application

Cette section porte sur les modifications apportées aux fichiers suivants:

  • main.py : permet d'ajouter l'utilisation des files d'attente de retrait à l'application principale.
  • templates/index.html : mettez à jour le modèle Web pour afficher les nouvelles données

Importations et constantes

La première étape consiste à ajouter une importation et plusieurs constantes afin de prendre en charge les files d'attente de retrait:

  • Ajoutez une importation de la bibliothèque Task Queue, google.appengine.api.taskqueue.
  • Ajoutez trois constantes pour permettre de louer le nombre maximal de tâches d'extraction (TASKS) pendant une heure (HOUR) depuis notre file d'attente de retrait (QUEUE).
  • Ajoutez une constante pour afficher les visites les plus récentes ainsi que les principaux visiteurs (LIMIT).

Vous trouverez ci-dessous le code d'origine et ce à quoi il ressemble après ces mises à jour:

AVANT:

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

app = Flask(__name__)

APRÈS:

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

HOUR = 3600
LIMIT = 10
TASKS = 1000
QNAME = 'pullq'
QUEUE = taskqueue.Queue(QNAME)
app = Flask(__name__)

Ajouter une tâche d'extraction (collecter des données pour la tâche et créer une tâche dans la file d'attente de retrait)

Le modèle de données Visit reste le même, tout comme l'interrogation des visites à afficher dans fetch_visits(). La seule modification requise dans cette partie du code se trouve dans store_visit(). En plus d'enregistrer la visite, ajoutez une tâche à la file d'attente avec l'adresse IP du visiteur afin que le nœud de calcul puisse incrémenter le compteur de visiteurs.

AVANT:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)

def store_visit(remote_addr, user_agent):
    'create new Visit entity in Datastore'
    Visit(visitor='{}: {}'.format(remote_addr, user_agent)).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)

def store_visit(remote_addr, user_agent):
    'create new Visit in Datastore and queue request to bump visitor count'
    Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
    QUEUE.add(taskqueue.Task(payload=remote_addr, method='PULL'))

def fetch_visits(limit):
    'get most recent visits'
    return Visit.query().order(-Visit.timestamp).fetch(limit)

Créer un modèle de données et une fonction de requête pour le suivi des visiteurs

Ajoutez un modèle de données VisitorCount pour suivre les visiteurs. il doit comporter des champs pour l'élément visitor lui-même, ainsi qu'un counter entier pour suivre le nombre de visites. Ajoutez ensuite une fonction (ou un classmethod Python) nommée fetch_counts() pour interroger et renvoyer les principaux visiteurs dans l'ordre décroissant. Ajoutez la classe et la fonction juste en dessous du corps de fetch_visits():

class VisitorCount(ndb.Model):
    visitor = ndb.StringProperty(repeated=False, required=True)
    counter = ndb.IntegerProperty()

def fetch_counts(limit):
    'get top visitors'
    return VisitCount.query().order(-VisitCount.counter).fetch(limit)

Ajouter un code de nœud de calcul

Ajoutez une fonction log_visitors() pour enregistrer les visiteurs via une requête GET envoyée à /log. Elle utilise un dictionnaire/hachage pour suivre le nombre de visiteurs le plus récent, en louant autant de tâches que possible pendant une heure. Pour chaque tâche, toutes les visites effectuées par un même visiteur sont comptabilisées. Une fois les décomptes effectués, l'application met à jour toutes les entités VisitorCount correspondantes déjà dans Datastore ou en crée d'autres si nécessaire. La dernière étape renvoie un message en texte brut indiquant le nombre de visiteurs enregistrés pour le nombre de tâches traitées. Ajoutez cette fonction à main.py, juste en dessous de fetch_counts():

@app.route('/log')
def log_visitors():
    'worker processes recent visitor counts and updates them in Datastore'
    # tally recent visitor counts from queue then delete those tasks
    tallies = {}
    tasks = QUEUE.lease_tasks(HOUR, TASKS)
    for task in tasks:
        visitor = task.payload
        tallies[visitor] = tallies.get(visitor, 0) + 1
    if tasks:
        QUEUE.delete_tasks(tasks)

    # increment those counts in Datastore and return
    for visitor in tallies:
        counter = VisitorCount.query(VisitorCount.visitor == visitor).get()
        if not counter:
            counter = VisitorCount(visitor=visitor, counter=0)
            counter.put()
        counter.counter += tallies[visitor]
        counter.put()
    return 'DONE (with %d task[s] logging %d visitor[s])\r\n' % (
            len(tasks), len(tallies))

Mettre à jour le gestionnaire principal avec les nouvelles données d'affichage

Pour afficher les principaux visiteurs, mettez à jour le gestionnaire principal root() pour appeler fetch_counts(). De plus, le modèle sera mis à jour pour afficher le nombre de visiteurs les plus performants et les visites les plus récentes. Regroupez le nombre de visiteurs et les visites les plus récentes depuis l'appel à fetch_visits() dans un seul élément context à transmettre au modèle Web. Vous trouverez ci-dessous le code avant et après cette modification:

AVANT:

@app.route('/')
def root():
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)
    return render_template('index.html', visits=visits)

APRÈS:

@app.route('/')
def root():
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    context = {
        'limit':  LIMIT,
        'visits': fetch_visits(LIMIT),
        'counts': fetch_counts(LIMIT),
    }
    return render_template('index.html', **context)

Voici toutes les modifications requises pour main.py. Voici une représentation graphique de ces modifications à titre d'illustration. Elle vous donne une idée générale des modifications que vous apportez à main.py:

ad5fd3345efc13d0.png

Mettre à jour le modèle Web avec les nouvelles données display

Le modèle Web templates/index.html doit être mis à jour pour afficher les principaux visiteurs en plus de la charge utile normale des visiteurs les plus récents. Déposez les principaux visiteurs et leur nombre dans un tableau en haut de la page, et continuez à afficher les visites les plus récentes comme auparavant. La seule autre modification consiste à spécifier le nombre affiché via la variable limit plutôt que de le coder en dur. Voici les modifications à apporter à votre modèle Web:

AVANT:

<!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>

APRÈS:

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

<h1>VisitMe example</h1>

<h3>Top {{ limit }} visitors</h3>
<table border=1 cellspacing=0 cellpadding=2>
    <tr><th>Visitor</th><th>Visits</th></tr>
{% for count in counts %}
    <tr><td>{{ count.visitor|e }}</td><td align="center">{{ count.counter }}</td></tr>
{% endfor %}
</table>

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

Vous venez de terminer les modifications nécessaires en ajoutant l'utilisation des tâches d'extraction de la file d'attente de tâches App Engine à l'exemple d'application du module 1. Votre répertoire représente à présent l'application exemple du module 18 et doit contenir les fichiers suivants:

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

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. Exécutez le nœud de calcul séparément pour traiter le nombre de visiteurs. Après la validation de l'application, effectuez toutes les étapes de nettoyage et réfléchissez aux prochaines étapes.

Déployer et vérifier l'application

Assurez-vous d'avoir déjà configuré votre file d'attente de retrait comme nous l'avons fait vers le début de cet atelier de programmation avec gcloud app deploy queue.yaml. Si c'est le cas et que votre application exemple est prête à l'emploi, déployez-la avec gcloud app deploy. Le résultat doit être identique à celui de l'application du module 1, sauf qu'elle inclut désormais une section "Principaux visiteurs". en haut:

b667551dcbab1a09.png

Même si l'interface Web mise à jour affiche les principaux visiteurs et les visites les plus récentes, notez que le nombre de visiteurs n'inclut pas cette visite. L'application affiche le nombre de visiteurs précédents tout en supprimant une nouvelle tâche incrémentant le nombre de ce visiteur dans la file d'attente d'extraction, une tâche en attente de traitement.

Vous pouvez exécuter la tâche en appelant /log de différentes manières:

Par exemple, si vous utilisez curl pour envoyer une requête GET à /log, le résultat ressemblera à ceci, si vous avez fourni votre PROJECT_ID:

$ curl https://PROJECT_ID.appspot.com/log
DONE (with 1 task[s] logging 1 visitor[s])

Le nouveau décompte sera ensuite reflété lors de la prochaine visite du site Web. Et voilà !

Félicitations ! Vous avez terminé cet atelier de programmation qui vous a permis d'ajouter le service de file d'attente d'extraction de la file d'attente de tâches App Engine à l'exemple d'application. Il est maintenant prêt pour la migration vers Cloud Pub/Sub, Cloud NDB et Python 3 dans le module 19.

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. Vous avez ajouté la prise en charge du suivi des visiteurs, et vous avez ainsi implémenté l'application exemple du module 18. Lors de la prochaine migration, vous mettrez à niveau les tâches de retrait App Engine vers Cloud Pub/Sub. Depuis fin 2021, les utilisateurs ne sont plus obligés de migrer vers Cloud Pub/Sub pour passer à Python 3. Vous trouverez plus d'informations à ce sujet dans la section suivante.

Pour en savoir plus sur la migration vers Cloud Pub/Sub, reportez-vous à l'atelier de programmation du module 19. Il existe également d'autres migrations à envisager, telles que Cloud Datastore, Cloud Memorystore, Cloud Storage ou Cloud Tasks (files d'attente d'envoi). 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 compatibilité de nombreux services groupés aux environnements d'exécution de 2e génération (qui disposent d'un environnement d'exécution de 1re génération). Par conséquent, vous n'êtes plus obligé de migrer des services groupés tels que la file d'attente de tâches App Engine vers des services cloud autonomes ou des services tiers tels que Cloud Pub/Sub lorsque vous transférez 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 18, vous trouverez ci-dessous les versions Python 3 de l'application du module 1 portées vers Python 3 et qui utilisent encore App Engine NDB. (Une version Python 3 de l'application du module 18 sera également disponible à un moment donné.)

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 1 (START) et 18 (FINISH). Ils sont également accessibles depuis le dépôt de toutes les migrations d'ateliers de programmation App Engine. clonez-le ou téléchargez un fichier ZIP.

Atelier de programmation

Python 2

Python 3

Module 1

code

code (non présenté dans ce tutoriel)

Module 18 (cet atelier de programmation)

code

N/A

Références en ligne

Vous trouverez ci-dessous des ressources pertinentes pour ce tutoriel:

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

Plate-forme App Engine

Documentation App Engine

Environnement d'exécution App Engine (environnement standard) Python 2

Environnement d'exécution App Engine (environnement standard) Python 3

Différences entre Python 2 et Trois environnements d'exécution App Engine (environnement standard)

Guide de migration App Engine (environnement standard) pour Python 2 vers 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)

Compatibilité à long terme avec les anciens environnements d'exécution

Exemples de migration de la documentation

Autres informations sur le cloud

Vidéos

Licence

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