Come utilizzare la coda di attività di App Engine (attività di pull) nelle app Flask (modulo 18)

1. Panoramica

La serie di codelab Serverless Migration Station (tutorial pratici e self-service) e i video correlati mirano ad aiutare gli sviluppatori Google Cloud serverless a modernizzare le applicazioni guidandoli attraverso una o più migrazioni, principalmente abbandonando i servizi legacy. In questo modo le tue app saranno più portabili e avrai più opzioni e flessibilità, consentendoti di integrare e accedere a una gamma più ampia di prodotti Cloud e di eseguire più facilmente l'upgrade a release delle lingue più recenti. Pur concentrandosi inizialmente sui primi utenti di Cloud, principalmente sviluppatori di App Engine (ambiente standard), questa serie è sufficientemente ampia da includere altre piattaforme serverless come Cloud Functions e Cloud Run, o altrove, se applicabile.

Questo codelab ti insegna come includere e utilizzare le attività pull della coda di attività di App Engine nell'app di esempio del codelab del Modulo 1. Aggiungiamo il suo utilizzo delle attività pull in questo tutorial del modulo 18, quindi eseguiamo la migrazione di questo utilizzo in Cloud Pub/Sub nel modulo 19. Coloro che utilizzano le code di attività per le attività push verranno invece migrate a Cloud Tasks e dovranno fare riferimento ai moduli 7-9.

Imparerai a utilizzare

  • Utilizzare l'API Task Queue/il servizio in bundle di App Engine
  • Aggiungi l'utilizzo delle code in modalità pull a un'app NDB di Python 2 Flask App Engine di base

Che cosa ti serve

Sondaggio

Come utilizzerai questo tutorial?

Solo lettura Leggilo e completa gli esercizi

Come valuteresti la tua esperienza con Python?

Principiante Livello intermedio Eccellente

Come giudichi la tua esperienza di utilizzo dei servizi Google Cloud?

Principiante Livello intermedio Eccellente

2. Sfondo

Per eseguire la migrazione dalle attività pull della coda di attività di App Engine, aggiungine l'utilizzo all'app NDB e a Flask esistente di App Engine risultante dal codelab del Modulo 1. L'app di esempio mostra le visite più recenti all'utente finale. Nessun problema, ma è ancora più interessante monitorare i visitatori per vedere chi li visita di più.

Potremmo utilizzare attività push per questo numero di visitatori, ma vogliamo dividere la responsabilità tra l'app di esempio, il cui compito è registrare le visite e rispondere immediatamente agli utenti, e un "lavoratore" designato. il cui compito è conteggiare il numero di visitatori al di fuori del normale flusso di lavoro richiesta-risposta.

Per implementare questo design, aggiungeremo l'utilizzo di code pull nell'applicazione principale, oltre a supportare la funzionalità worker. Il worker può essere eseguito come un processo separato (come un'istanza di backend o un codice in esecuzione su una VM sempre attiva), un cron job o una richiesta HTTP da riga di comando di base utilizzando curl o wget. Dopo questa integrazione, puoi eseguire la migrazione dell'app in Cloud Pub/Sub nel codelab successivo (Modulo 19).

Questo tutorial illustra i seguenti passaggi:

  1. Configurazione/pre-lavoro
  2. Aggiorna configurazione
  3. Modifica il codice dell'applicazione

3. Configurazione/pre-lavoro

In questa sezione viene spiegato come:

  1. Configura il progetto Cloud
  2. Ottieni app di esempio di riferimento
  3. (Ri)Esegui il deployment e convalida l'app di riferimento

Questi passaggi assicurano di iniziare con un codice funzionante.

1. Configura il progetto

Se hai completato il codelab del Modulo 1, riutilizza lo stesso progetto (e lo stesso codice). In alternativa, crea un nuovo progetto o riutilizza un altro progetto esistente. Assicurati che il progetto abbia un account di fatturazione attivo e un'app App Engine abilitata. Trova il tuo ID progetto perché ti servirà più volte in questo codelab e utilizzalo ogni volta che incontri la variabile PROJECT_ID.

2. Ottieni app di esempio di riferimento

Uno dei prerequisiti di questo codelab è avere un'app App Engine del Modulo 1 funzionante. Completa il codelab del Modulo 1 (consigliato) o copia l'app Modulo 1 dal repository. Che tu utilizzi il tuo o il nostro, il codice del Modulo 1 è il punto in cui "INIZIAMO". Questo codelab ti guiderà in ogni passaggio, concludendo con un codice simile a quello presente nella cartella del repository del modulo 18 "FINISH".

Indipendentemente dall'app del Modulo 1 che utilizzi, la cartella dovrebbe avere l'aspetto seguente, possibilmente con una cartella lib:

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

3. (Ri)Esegui il deployment dell'app di base

Esegui questi passaggi per eseguire il deployment dell'app del Modulo 1:

  1. Elimina la cartella lib, se presente, ed esegui: pip install -t lib -r requirements.txt per ricompilare lib. Potresti dover utilizzare il comando pip2 se hai installato sia Python 2 sia Python 3.
  2. Assicurati di aver installato e iniziato lo strumento a riga di comando gcloud e di averne controllato l'utilizzo.
  3. Imposta il tuo progetto Cloud su gcloud config set project PROJECT_ID se non vuoi inserire il valore PROJECT_ID con ogni comando gcloud emesso.
  4. Esegui il deployment dell'app di esempio con gcloud app deploy
  5. Verifica che l'app del Modulo 1 funzioni come previsto e mostri le visite più recenti (illustrate di seguito)

a7a9d2b80d706a2b.png

4. Aggiorna configurazione

Non sono necessarie modifiche ai file di configurazione standard di App Engine (app.yaml, requirements.txt, appengine_config.py). Aggiungi invece un nuovo file di configurazione, queue.yaml, con il seguente contenuto, collocandolo nella stessa directory di primo livello:

queue:
- name: pullq
  mode: pull

Il file queue.yaml specifica tutte le code di attività esistenti per la tua app (tranne la coda [push] default, che viene creata automaticamente da App Engine). In questo caso, ne esiste una sola, una coda di pull denominata pullq. App Engine richiede che l'istruzione mode sia specificata come pull, altrimenti crea una coda in modalità push per impostazione predefinita. Scopri di più sulla creazione di code in modalità pull nella documentazione. Consulta anche la pagina di riferimento di queue.yaml per altre opzioni.

Esegui il deployment di questo file separatamente dalla tua app. Utilizzerai comunque gcloud app deploy, ma dovrai anche specificare queue.yaml nella riga di comando:

$ 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. Modifica il codice dell'applicazione

Questa sezione contiene aggiornamenti ai seguenti file:

  • main.py: aggiungi l'utilizzo di code in modalità pull all'applicazione principale
  • templates/index.html: aggiorna il modello web per visualizzare i nuovi dati

Importazioni e costanti

Il primo passaggio consiste nell'aggiungere una nuova importazione e diverse costanti per supportare le code in modalità pull:

  • Aggiungi un'importazione della libreria delle code di attività, google.appengine.api.taskqueue.
  • Aggiungi tre costanti per supportare il leasing del numero massimo di attività pull (TASKS) per un'ora (HOUR) dalla nostra coda in modalità pull (QUEUE).
  • Aggiungi una costante per visualizzare le visite più recenti e i visitatori principali (LIMIT).

Di seguito è riportato il codice originale e il suo aspetto dopo aver apportato questi aggiornamenti:

PRIMA:

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

app = Flask(__name__)

DOPO:

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__)

Aggiungi un'attività di pull (raccogli i dati per l'attività e crea un'attività nella coda di pull)

Il modello dei dati Visit rimane invariato, così come l'esecuzione di query per le visite da visualizzare in fetch_visits(). L'unica modifica richiesta in questa parte del codice è in store_visit(). Oltre a registrare la visita, aggiungi un'attività alla coda in modalità pull con l'indirizzo IP del visitatore, in modo che il worker possa incrementare il contatore dei visitatori.

PRIMA:

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)

DOPO:

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)

Crea un modello dei dati e una funzione di query per il monitoraggio dei visitatori

Aggiungi un modello dei dati VisitorCount per monitorare i visitatori; deve avere campi per il visitor stesso e un counter intero per monitorare il numero di visite. Quindi aggiungi una nuova funzione (in alternativa, può essere un classmethod Python) denominata fetch_counts()per eseguire query e restituire i visitatori principali in ordine decrescente. Aggiungi la classe e la funzione sotto il corpo di 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)

Aggiungi codice worker

Aggiungi una nuova funzione log_visitors() per registrare i visitatori tramite una richiesta GET a /log. Utilizza un dizionario/hash per tenere traccia dei conteggi dei visitatori più recenti, concedendo in leasing il maggior numero possibile di attività per un'ora. Per ogni attività, vengono conteggiate tutte le visite dello stesso visitatore. Con i conteggi a portata di mano, l'app aggiorna quindi tutte le entità VisitorCount corrispondenti già in Datastore o ne crea di nuove, se necessario. L'ultimo passaggio restituisce un messaggio di testo normale che indica quanti visitatori si sono registrati dopo aver ottenuto il numero di attività elaborate. Aggiungi questa funzione a main.py proprio sotto 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))

Aggiorna il gestore principale con i nuovi dati di visualizzazione

Per visualizzare i visitatori principali, aggiorna il gestore principale root() per richiamare fetch_counts(). Inoltre, il modello verrà aggiornato per mostrare il numero di visitatori principali e delle visite più recenti. Raggruppa i conteggi dei visitatori insieme alle visite più recenti dalla chiamata a fetch_visits() e inseriscile in un singolo context da trasferire al modello web. Di seguito è riportato il codice prima e dopo l'applicazione della modifica:

PRIMA:

@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)

DOPO:

@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)

Queste sono tutte le modifiche richieste per main.py. Di seguito puoi trovare una rappresentazione grafica di questi aggiornamenti a scopo illustrativo per darti un'idea generale delle modifiche che stai apportando a main.py:

ad5fd3345efc13d0.png

Aggiornare il modello web con i nuovi dati della Rete Display

Il modello web templates/index.html richiede un aggiornamento per visualizzare i visitatori principali oltre al normale payload dei visitatori più recenti. Trascina i visitatori principali e i relativi conteggi in una tabella nella parte superiore della pagina e continua a visualizzare le visite più recenti come prima. L'unica altra modifica consiste nello specificare il numero mostrato tramite la variabile limit invece di farlo tramite hardcoded. Di seguito sono riportati gli aggiornamenti da apportare al modello web:

PRIMA:

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

DOPO:

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

Con questo si concludeno le modifiche necessarie che aggiungono l'utilizzo delle attività pull della coda di attività di App Engine all'app di esempio del Modulo 1. La tua directory ora rappresenta l'app di esempio del Modulo 18 e dovrebbe contenere questi file:

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

6. Riepilogo/Pulizia

In questa sezione si conclude questo codelab eseguendo il deployment dell'app e verificando che funzioni come previsto e in qualsiasi output riportato. Esegui il worker separatamente per elaborare i conteggi dei visitatori. Dopo la convalida dell'app, esegui tutti i passaggi di pulizia e considera i passaggi successivi.

Esegui il deployment e verifica l'applicazione

Assicurati di aver già impostato la coda in modalità pull come abbiamo fatto nella parte superiore di questo codelab con gcloud app deploy queue.yaml. Se la procedura è stata completata e la tua app di esempio è pronta, esegui il deployment dell'app con gcloud app deploy. L'output dovrebbe essere identico a quello dell'app del Modulo 1, tranne per il fatto che ora include un "visitatori principali" tabella in alto:

b667551dcbab1a09.png

Anche se il frontend web aggiornato mostra i visitatori principali e le visite più recenti, tieni presente che il numero di visitatori non include questa visita. L'app visualizza il numero di visitatori precedenti eliminando una nuova attività che incrementa il numero di visitatori nella coda di pull, un'attività in attesa di essere elaborata.

Puoi eseguire l'attività chiamando /log in diversi modi:

Ad esempio, se utilizzi curl per inviare una richiesta GET a /log, l'output sarà simile al seguente, se hai fornito il valore PROJECT_ID:

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

Il conteggio aggiornato verrà quindi applicato alla successiva visita al sito web. È tutto.

Complimenti per aver completato questo codelab per l'aggiunta dell'utilizzo del servizio coda di pull della coda di attività di App Engine all'app di esempio. Ora è pronto per la migrazione a Cloud Pub/Sub, Cloud NDB e Python 3 nel modulo 19.

Esegui la pulizia

Generale

Se per il momento hai finito, ti consigliamo di disabilitare l'app App Engine per evitare di incorrere in fatturazione. Tuttavia, se desideri eseguire altri test o sperimentarli, la piattaforma App Engine ha una quota senza costi, pertanto, se non superi il livello di utilizzo, non ti verrà addebitato alcun costo. Questo riguarda il computing, ma potrebbero essere addebitati costi anche per i servizi App Engine pertinenti, quindi consulta la pagina dei prezzi per ulteriori informazioni. Se la migrazione coinvolge altri servizi Cloud, questi vengono fatturati separatamente. In entrambi i casi, se applicabile, consulta la sezione "Specifici di questo codelab" di seguito.

Per garantire la piena divulgazione, il deployment su una piattaforma di serverless computing di Google Cloud come App Engine comporta costi minori di build e archiviazione. Cloud Build e Cloud Storage hanno una quota senza costi specifica. Lo spazio di archiviazione dell'immagine esaurisce una parte della quota. Tuttavia, potresti risiedere in una regione che non ha un livello senza costi, quindi tieni presente l'utilizzo dello spazio di archiviazione per ridurre al minimo i costi potenziali. "cartelle" specifiche di Cloud Storage da esaminare includono:

  • 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
  • I link allo spazio di archiviazione riportati sopra dipendono dalla tua PROJECT_ID e dalla tua *LOC*azione, ad esempio "us" se la tua app è ospitata negli Stati Uniti.

Se invece non intendi continuare con questa applicazione o con altri codelab di migrazione correlati e vuoi eliminare tutto completamente, chiudi il progetto.

Specifico di questo codelab

I servizi elencati di seguito sono esclusivi per questo codelab. Per ulteriori informazioni, fai riferimento alla documentazione di ciascun prodotto:

Passaggi successivi

In questa "migrazione", Hai aggiunto l'utilizzo della coda push della coda di attività all'app di esempio del modulo 1, aggiungendo il supporto per il monitoraggio dei visitatori e implementando così l'app di esempio del modulo 18. Nella prossima migrazione eseguirai l'upgrade delle attività pull di App Engine a Cloud Pub/Sub. A partire dalla fine del 2021, gli utenti non sono più tenuti a eseguire la migrazione a Cloud Pub/Sub quando eseguono l'upgrade a Python 3. Scopri di più nella prossima sezione.

Per eseguire la migrazione a Cloud Pub/Sub, fai riferimento al codelab del modulo 19. Oltre a questo, ci sono altre migrazioni da considerare, come Cloud Datastore, Cloud Memorystore, Cloud Storage o Cloud Tasks (code push). Esistono anche migrazioni tra prodotti a Cloud Run e Cloud Functions. È possibile accedere a tutti i contenuti di Serverless Migration Station (codelab, video, codice sorgente [se disponibile]) nel relativo repository open source.

7. Migrazione a Python 3

Nell'autunno 2021, il team di App Engine ha esteso il supporto di molti dei servizi in bundle ai runtime di 2a generazione (che hanno un runtime di 1a generazione). Di conseguenza, non devi più eseguire la migrazione da servizi in bundle come la coda di attività di App Engine a servizi cloud autonomi o di terze parti come Cloud Pub/Sub quando esegui la portabilità della tua app in Python 3. In altre parole, puoi continuare a utilizzare la coda di attività nelle app App Engine in Python 3, purché adatta il codice per accedere ai servizi in bundle dai runtime di nuova generazione.

Per ulteriori informazioni su come eseguire la migrazione a Python 3 dell'utilizzo dei servizi in bundle, consulta il codelab del Modulo 17 e il video corrispondente. Sebbene l'argomento non rientri nell'ambito del Modulo 18, di seguito trovi il link alle versioni Python 3 dell'app del Modulo 1 trasferite a Python 3 e che utilizzano ancora l'NDB di App Engine. (A un certo punto, verrà resa disponibile anche una versione Python 3 dell'app del Modulo 18.)

8. Risorse aggiuntive

Di seguito sono elencate le risorse aggiuntive per gli sviluppatori che esplorano ulteriormente questo modulo di migrazione o i prodotti correlati, nonché i prodotti correlati. tra cui posizioni in cui fornire feedback su questi contenuti, link al codice e vari documenti che potrebbero esserti utili.

Problemi/feedback del codelab

Se riscontri problemi con questo codelab, cercali prima di procedere con l'invio. Link per eseguire ricerche e creare nuovi problemi:

Risorse di migrazione

I link alle cartelle repository per il modulo 1 (START) e il modulo 18 (FINISH) sono disponibili nella tabella seguente. Sono inoltre accessibili dal repository per tutte le migrazioni del codelab di App Engine. clonarlo o scaricare un file ZIP.

Codelab

Python 2

Python 3

Module 1

codice

code (non presente in questo tutorial)

Modulo 18 (questo codelab)

codice

N/A

Riferimenti online

Di seguito sono riportate le risorse pertinenti per questo tutorial:

Coda di attività App Engine

Piattaforma App Engine

Documentazione di App Engine

Runtime Python 2 App Engine (ambiente standard)

Runtime Python 3 per App Engine (ambiente standard)

Differenze tra Python 2 e 3 runtime App Engine (ambiente standard)

Guida alla migrazione di Python da 2 a 3 per App Engine (ambiente standard)

Informazioni su prezzi e quote di App Engine

Lancio della piattaforma App Engine di seconda generazione (2018)

Assistenza a lungo termine per i runtime legacy

Esempi di migrazione della documentazione

Altre informazioni sul cloud

Video

Licenza

Questo lavoro è concesso in licenza ai sensi di una licenza Creative Commons Attribution 2.0 Generic.