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 proprie 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.
Lo scopo di questo codelab è mostrare agli sviluppatori di App Engine Python 2 come eseguire la migrazione dalle attività di pull della coda delle attività di App Engine a Cloud Pub/Sub. È prevista anche una migrazione implicita dall'NDB di App Engine a Cloud NDB per l'accesso a Datastore (trattata principalmente nel Modulo 2) nonché un upgrade a Python 3.
Nel modulo 18 imparerai ad aggiungere l'utilizzo delle attività pull nell'app. In questo modulo, prenderai l'app completa del modulo 18 ed eseguirai la migrazione di questo utilizzo a Cloud Pub/Sub. 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
- Sostituisci l'utilizzo della coda di attività di App Engine (attività pull) con Cloud Pub/Sub.
- Sostituisci l'utilizzo dell'NDB di App Engine con Cloud NDB (vedi anche il Modulo 2)
- Porta l'app in Python 3
Che cosa ti serve
- Un progetto piattaforma Google Cloud con un account di fatturazione Google Cloud attivo
- Competenze Python di base
- Conoscenza pratica dei comandi Linux più comuni
- Conoscenza di base dello sviluppo e del deployment delle app App Engine
- Un'app di esempio di App Engine del Modulo 18 funzionante
Sondaggio
Come utilizzerai questo tutorial?
Come valuteresti la tua esperienza con Python?
Come giudichi la tua esperienza di utilizzo dei servizi Google Cloud?
2. Sfondo
La coda di attività di App Engine supporta sia le attività push che pull. Per migliorare la portabilità delle applicazioni, Google Cloud consiglia di eseguire la migrazione da servizi in bundle legacy, come Task Queue, di altri servizi Cloud autonomi o equivalenti di terze parti.
- Gli utenti dell'attività push della coda di attività devono eseguire la migrazione a Cloud Tasks.
- Gli utenti dell'attività pull della coda di attività devono eseguire la migrazione a Cloud Pub/Sub.
I Moduli di migrazione 7-9 trattano la migrazione delle attività push, mentre i Moduli 18-19 si concentrano sulla migrazione delle attività di pull. Mentre Cloud Tasks corrisponde maggiormente alle attività di push della coda di attività, Pub/Sub non è un analogo alle attività di pull della coda di attività.
Pub/Sub ha più caratteristiche rispetto alla funzionalità pull fornita dalla coda di attività. Ad esempio, Pub/Sub dispone anche della funzionalità push, tuttavia Cloud Tasks è più simile alle attività push delle code di attività, quindi il push di Pub/Sub non è coperto da nessuno dei Moduli di migrazione. Questo codelab del modulo 19 illustra il passaggio del meccanismo di accodamento dalle code di pull della coda di attività a Pub/Sub e la migrazione dall'NDB di App Engine a Cloud NDB per l'accesso a Datastore, ripetendo la migrazione del Modulo 2.
Mentre il codice del modulo 18 è "pubblicizzato", Come app di esempio Python 2, l'origine stessa è compatibile con Python 2 e 3 e rimane tale anche dopo la migrazione a Cloud Pub/Sub (e Cloud NDB) qui nel Modulo 19.
Questo tutorial illustra i seguenti passaggi:
- Configurazione/pre-lavoro
- Aggiorna configurazione
- Modifica il codice dell'applicazione
3. Configurazione/pre-lavoro
In questa sezione viene spiegato come:
- Configura il progetto Cloud
- Ottieni app di esempio di riferimento
- (Ri)Esegui il deployment e convalida l'app di riferimento
- Abilita nuovi servizi/API Google Cloud
Questi passaggi assicurano che tu stia iniziando con il codice funzionante e che sia pronto per la migrazione ai servizi Cloud.
1. Configura il progetto
Se hai completato il codelab del Modulo 18, 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 l'ID progetto perché ti serve a portata di mano durante questo codelab, utilizzandolo ogni volta che incontri la variabile PROJECT_ID
.
2. Ottieni app di esempio di riferimento
Uno dei prerequisiti è un'app App Engine con Modulo 18 funzionante, quindi completa il codelab (consigliato; link riportato sopra) o copia il codice del Modulo 18 dal repository. Che tu utilizzi il tuo o il nostro, questo è il punto in cui inizieremo ("START"). Questo codelab ti guiderà attraverso la migrazione, concludendo con un codice simile a quello presente nella cartella dei repository del modulo 19 ("FINISH").
- AVVIA: cartella del modulo 18 (Python 2)
- FINISH: cartella del modulo 19 (Python 2 e 3)
- Intero repository (per clonare o scaricare il file ZIP)
Indipendentemente dall'app del Modulo 18 che utilizzi, la cartella dovrebbe avere l'aspetto seguente, possibilmente con una cartella lib
:
$ ls README.md appengine_config.py queue.yaml templates app.yaml main.py requirements.txt
3. (Ri)Esegui il deployment e convalida l'app di riferimento
Esegui questi passaggi per eseguire il deployment dell'app del Modulo 18:
- Elimina la cartella
lib
, se presente, ed eseguipip install -t lib -r requirements.txt
per ricompilarelib
. Potresti dover usare invecepip2
se hai installato sia Python 2 che 3 sulla macchina di sviluppo. - Assicurati di aver installato e iniziato lo strumento a riga di comando
gcloud
e di averne controllato il utilizzo. - (Facoltativo) Imposta il progetto Cloud su
gcloud config set project
PROJECT_ID
se non vuoi inserirePROJECT_ID
con ogni comandogcloud
che emetti. - Esegui il deployment dell'app di esempio con
gcloud app deploy
- Verifica che l'app venga eseguita come previsto senza problemi. Se hai completato il codelab del Modulo 18, l'app mostra i visitatori principali insieme alle visite più recenti (illustrate di seguito). In caso contrario, potrebbe non essere presente alcun numero di visitatori da visualizzare.
Prima di eseguire la migrazione dell'app di esempio del Modulo 18, devi abilitare i servizi Cloud che verranno utilizzati dall'app modificata.
4. Abilita nuovi servizi/API Google Cloud
L'app precedente utilizzava servizi in bundle di App Engine che non richiedono una configurazione aggiuntiva, a differenza dei servizi Cloud autonomi e l'app aggiornata impiegherà sia Cloud Pub/Sub che Cloud Datastore (tramite la libreria client Cloud NDB). App Engine e entrambe le API Cloud dispongono di " Always Free" e, se rimani al di sotto di questi limiti, non ti viene addebitato alcun costo per il completamento di questo tutorial. Le API Cloud possono essere abilitate dalla console Cloud o dalla riga di comando, a seconda delle preferenze.
Dalla console Cloud
Nella console Cloud, vai alla pagina Libreria del gestore API (per il progetto corretto) e cerca le API Cloud Datastore e Cloud Pub/Sub utilizzando la barra di ricerca al centro della pagina:
Fai clic sul pulsante Abilita per ciascuna API separatamente. Ti potrebbero essere richiesti i dati di fatturazione. Ad esempio, questa è la pagina della libreria API Cloud Pub/Sub:
Dalla riga di comando
Sebbene l'abilitazione delle API dalla console sia visivamente informativa, alcuni preferiscono la riga di comando. Esegui il comando gcloud services enable pubsub.googleapis.com datastore.googleapis.com
per abilitare entrambe le API contemporaneamente:
$ gcloud services enable pubsub.googleapis.com datastore.googleapis.com Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.
Ti potrebbero essere richiesti i dati di fatturazione. Se vuoi abilitare altre API Cloud e vuoi conoscere i relativi URI, puoi trovarli nella parte inferiore della pagina della libreria di ciascuna API. Ad esempio, osserva pubsub.googleapis.com
come "Nome servizio". in fondo alla pagina Pub/Sub appena sopra.
Una volta completati i passaggi, il progetto potrà accedere alle API. Ora è il momento di aggiornare l'applicazione per utilizzare queste API.
4. crea risorse Pub/Sub
Riassumendo l'ordine di sequenza del flusso di lavoro della coda di attività del modulo 18:
- Il modulo 18 ha utilizzato il file
queue.yaml
per creare una coda di pull denominatapullq
. - L'app aggiunge attività alla coda in modalità pull per monitorare i visitatori.
- Alla fine le attività vengono elaborate da un worker, noleggiate per un periodo di tempo limitato (un'ora).
- Le attività vengono eseguite per conteggiare i conteggi dei visitatori recenti.
- Le attività vengono eliminate dalla coda al completamento.
Stai per replicare un flusso di lavoro simile con Pub/Sub. La prossima sezione introduce la terminologia Pub/Sub di base, con tre diversi modi per creare le risorse Pub/Sub necessarie.
Terminologia della coda di attività di App Engine (pull) e di Cloud Pub/Sub
Il passaggio a Pub/Sub richiede una leggera modifica al vocabolario. Di seguito sono elencate le categorie principali insieme ai termini pertinenti di entrambi i prodotti. Consulta anche la guida alla migrazione, che offre confronti simili.
- Struttura dei dati in coda: con la coda di attività, i dati vengono inseriti in code di pull; con Pub/Sub, i dati passano in argomenti.
- Unità di dati in coda: le attività pull con coda di attività vengono chiamate messaggi con Pub/Sub.
- Responsabili di dati: con la coda di attività, i lavoratori accedono alle attività pull; con Pub/Sub, sono necessari abbonamenti/abbonati per ricevere i messaggi
- Estrazione dati: il leasing di un'attività pull è uguale al pull di un messaggio da un argomento (tramite una sottoscrizione).
- Pulizia/completamento: l'eliminazione di un'attività di una coda di attività da una coda in modalità pull quando hai finito è analoga alla conferma di un messaggio Pub/Sub
Anche se il prodotto per l'accodamento cambia, il flusso di lavoro rimane relativamente simile:
- Anziché una coda in modalità pull, l'app utilizza un argomento denominato
pullq
. - Anziché aggiungere attività a una coda in modalità pull, l'app invia messaggi a un argomento (
pullq
). - Anziché un worker che noleggia le attività dalla coda di pull, un sottoscrittore denominato
worker
estrae i messaggi dall'argomentopullq
. - L'app elabora i payload dei messaggi, aumentando il numero di visitatori in Datastore.
- Anziché eliminare le attività dalla coda in modalità pull, l'app riconosce i messaggi elaborati.
Con la coda di attività, la configurazione prevede la creazione della coda in pull. Con Pub/Sub, la configurazione richiede la creazione sia di un argomento che di una sottoscrizione. Nel modulo 18, abbiamo elaborato queue.yaml
al di fuori dell'esecuzione dell'app. ora lo stesso deve essere fatto con Pub/Sub.
Sono disponibili tre opzioni per la creazione di argomenti e sottoscrizioni:
- Dalla console Cloud
- Dalla riga di comando
- Dal codice (breve script Python)
Scegli una delle opzioni seguenti e segui le istruzioni corrispondenti per creare le tue risorse Pub/Sub.
Dalla console Cloud
Per creare un argomento dalla console Cloud:
- Vai alla pagina Argomenti Pub/Sub della console Cloud.
- Fai clic su Crea argomento in alto. si apre una nuova finestra di dialogo (vedi l'immagine sotto)
- Nel campo ID argomento, inserisci
pullq
. - Deseleziona tutte le opzioni selezionate e scegli Chiave di crittografia gestita da Google.
- Fai clic sul pulsante Crea argomento.
Ecco l'aspetto della finestra di dialogo per la creazione dell'argomento:
Ora che hai un argomento, devi creare una sottoscrizione per quell'argomento:
- Vai alla pagina Abbonamenti Pub/Sub della console Cloud.
- Fai clic su Crea abbonamento in alto (vedi l'immagine sotto).
- Inserisci
worker
nel campo ID abbonamento. - Seleziona
pullq
dal menu a discesa Seleziona un argomento Cloud Pub/Sub, annotando il suo "percorso completo" ad esempioprojects/PROJECT_ID/topics/pullq
- Per Tipo di recapito, seleziona Pull.
- Lascia invariate tutte le altre opzioni e fai clic sul pulsante Crea.
Ecco l'aspetto della schermata di creazione dell'abbonamento:
Puoi anche creare un'iscrizione dalla pagina Argomenti; questa "scorciatoia" potrebbe esserti utile per associare gli argomenti alle iscrizioni. Per scoprire di più sulla creazione degli abbonamenti, consulta la documentazione.
Dalla riga di comando
Gli utenti Pub/Sub possono creare argomenti e sottoscrizioni rispettivamente con i comandi gcloud pubsub topics create
TOPIC_ID
e gcloud pubsub subscriptions create
SUBSCRIPTION_ID
--topic=
TOPIC_ID
. L'esecuzione di questi elementi con un valore TOPIC_ID
di pullq
e un valore SUBSCRIPTION_ID
di worker
genera il seguente output per il progetto PROJECT_ID
:
$ gcloud pubsub topics create pullq Created topic [projects/PROJECT_ID/topics/pullq]. $ gcloud pubsub subscriptions create worker --topic=pullq Created subscription [projects/PROJECT_ID/subscriptions/worker].
Consulta anche questa pagina nella documentazione relativa alla guida rapida. L'utilizzo della riga di comando potrebbe semplificare i flussi di lavoro in cui argomenti e sottoscrizioni vengono creati regolarmente e tali comandi possono essere utilizzati negli script shell a questo scopo.
Dal codice (breve script Python)
Un altro modo per automatizzare la creazione di argomenti e sottoscrizioni è utilizzare l'API Pub/Sub nel codice sorgente. Di seguito è riportato il codice per lo script maker.py
nella cartella dei repository del Modulo 19.
from __future__ import print_function
import google.auth
from google.api_core import exceptions
from google.cloud import pubsub
_, PROJECT_ID = google.auth.default()
TOPIC = 'pullq'
SBSCR = 'worker'
ppc_client = pubsub.PublisherClient()
psc_client = pubsub.SubscriberClient()
TOP_PATH = ppc_client.topic_path(PROJECT_ID, TOPIC)
SUB_PATH = psc_client.subscription_path(PROJECT_ID, SBSCR)
def make_top():
try:
top = ppc_client.create_topic(name=TOP_PATH)
print('Created topic %r (%s)' % (TOPIC, top.name))
except exceptions.AlreadyExists:
print('Topic %r already exists at %r' % (TOPIC, TOP_PATH))
def make_sub():
try:
sub = psc_client.create_subscription(name=SUB_PATH, topic=TOP_PATH)
print('Subscription created %r (%s)' % (SBSCR, sub.name))
except exceptions.AlreadyExists:
print('Subscription %r already exists at %r' % (SBSCR, SUB_PATH))
try:
psc_client.close()
except AttributeError: # special Py2 handler for grpcio<1.12.0
pass
make_top()
make_sub()
L'esecuzione di questo script genera l'output previsto (a condizione che non ci siano errori):
$ python3 maker.py Created topic 'pullq' (projects/PROJECT_ID/topics/pullq) Subscription created 'worker' (projects/PROJECT_ID/subscriptions/worker)
La chiamata all'API per creare risorse già esistenti comporta un'eccezione google.api_core.exceptions.AlreadyExists
generata dalla libreria client, gestita dallo script in modo controllato:
$ python3 maker.py Topic 'pullq' already exists at 'projects/PROJECT_ID/topics/pullq' Subscription 'worker' already exists at 'projects/PROJECT_ID/subscriptions/worker'
Se non hai mai utilizzato Pub/Sub, consulta il white paper sull'architettura di Pub/Sub per ulteriori informazioni.
5. Aggiorna configurazione
Gli aggiornamenti della configurazione includono la modifica di vari file di configurazione e la creazione dell'equivalente delle code in modalità pull di App Engine, ma all'interno dell'ecosistema Cloud Pub/Sub.
Elimina code.yaml
La coda di attività non verrà più utilizzata, quindi elimina queue.yaml
perché Pub/Sub non utilizza questo file. Invece di creare una coda pull, dovrai creare un argomento Pub/Sub (e una sottoscrizione).
requirements.txt
Aggiungi sia google-cloud-ndb
che google-cloud-pubsub
a requirements.txt
in modo da partecipare a flask
dal Modulo 18. Il modulo 19 requirements.txt
aggiornato ora dovrebbe avere il seguente aspetto:
flask
google-cloud-ndb
google-cloud-pubsub
Questo file requirements.txt
non presenta numeri di versione, il che significa che sono selezionate le versioni più recenti. In caso di incompatibilità, segui la pratica standard che prevede l'uso dei numeri di versione per bloccare le versioni funzionanti di un'app.
app.yaml
Le modifiche a app.yaml
variano a seconda che tu stia utilizzando Python 2 o eseguendo l'upgrade a Python 3.
Python 2
L'aggiornamento precedente a requirements.txt
aggiunge l'utilizzo delle librerie client di Google Cloud. Queste ultime richiedono supporto aggiuntivo da parte di App Engine, ovvero un paio di librerie integrate, setuptools
e grpcio
. L'utilizzo delle librerie integrate richiede una sezione libraries
in app.yaml
e i numeri di versione della libreria o "più recenti" per conoscere le ultime novità sui server App Engine. Il modulo 18 app.yaml
non dispone ancora di una di queste sezioni:
PRIMA:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
Aggiungi una sezione libraries
a app.yaml
insieme alle voci per setuptools
e grpcio
, selezionando le versioni più recenti. Aggiungi anche una voce segnaposto runtime
per Python 3, commentato insieme alla release 3.x corrente, ad esempio 3.10, al momento della stesura di questo articolo. Con queste modifiche, app.yaml
ora appare così:
DOPO:
#runtime: python310
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: setuptools
version: latest
- name: grpcio
version: latest
Python 3
Per gli utenti Python 3 e app.yaml
, si tratta di rimuovere elementi. In questa sezione eliminerai la sezione handlers
, le istruzioni threadsafe
e api_version
e non creerai una sezione libraries
.
I runtime di seconda generazione non forniscono librerie di terze parti integrate, quindi non è necessaria una sezione libraries
in app.yaml
. Inoltre, non è più necessario copiare la copia (talvolta nota come fornitore o self-bundling) di pacchetti non di terze parti integrati. Devi elencare solo le librerie di terze parti utilizzate dalla tua app in requirements.txt
.
La sezione handlers
in app.yaml
consente di specificare gestori di applicazioni (script) e file statici. Poiché il runtime Python 3 richiede che i framework web eseguano il proprio routing, tutti i gestori di script devono essere modificati in auto
. Se la tua app (come quella del Modulo 18) non pubblica file statici, tutte le route saranno contrassegnate da auto
e non saranno quindi pertinenti. Di conseguenza, anche la sezione handlers
non è necessaria, quindi eliminala.
Infine, in Python 3 non vengono utilizzate né le istruzioni threadsafe
né le istruzioni api_version
, quindi elimina anche quelle. In sostanza, devi eliminare tutte le sezioni di app.yaml
in modo che rimanga solo l'istruzione runtime
, specificando una versione moderna di Python 3, ad esempio 3.10. Ecco come si presenta app.yaml
prima e dopo questi aggiornamenti:
PRIMA:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
DOPO:
runtime: python310
Per coloro che non sono pronti a eliminare tutto dal proprio app.yaml
per Python 3, abbiamo fornito un file alternativo app3.yaml
nella cartella dei repository del Modulo 19. Se vuoi utilizzarlo per i deployment, assicurati di aggiungere questo nome file alla fine del comando: gcloud app deploy app3.yaml
(in caso contrario, per impostazione predefinita verrà eseguito il deployment della tua app con il file Python 2 app.yaml
che hai lasciato invariato).
appengine_config.py
Se esegui l'upgrade a Python 3, non è necessario alcun appengine_config.py
, quindi eliminalo. Il motivo per cui non è necessario è che l'assistenza delle librerie di terze parti richiede solo di specificarle in requirements.txt
. Se siete utenti di Python 2, continuate a leggere.
Il modulo 18 appengine_config.py
contiene il codice appropriato per supportare le librerie di terze parti, ad esempio Flask e le librerie client di Cloud appena aggiunte a requirements.txt
:
PRIMA:
from google.appengine.ext import vendor
# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
Tuttavia, questo codice da solo non è sufficiente a supportare le librerie integrate appena aggiunte (setuptools
, grpcio
). Sono necessarie altre righe, quindi aggiorna appengine_config.py
in modo che abbia il seguente aspetto:
DOPO:
import pkg_resources
from google.appengine.ext import vendor
# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
# Add libraries to pkg_resources working set to find the distribution.
pkg_resources.working_set.add_entry(PATH)
Ulteriori dettagli sulle modifiche necessarie per supportare le librerie client di Cloud sono disponibili nella documentazione relativa alla migrazione dei servizi in bundle.
Altri aggiornamenti della configurazione
Se hai una cartella lib
, eliminala. Se sei un utente Python 2, reintegra la cartella lib
inviando il seguente comando:
pip install -t lib -r requirements.txt # or pip2
Se sul tuo sistema di sviluppo sono installati sia Python 2 che 3, potrebbe essere necessario utilizzare pip2
anziché pip
.
6. Modifica il codice dell'applicazione
Questa sezione presenta gli aggiornamenti del file dell'applicazione principale, main.py
, che sostituiscono l'uso delle code in pull delle code di attività di App Engine con Cloud Pub/Sub. Nessuna modifica al modello web templates/index.html
. Entrambe le app devono funzionare in modo identico e mostrare gli stessi dati.
Aggiorna importazioni e inizializzazione
Esistono diversi aggiornamenti alle importazioni e all'inizializzazione:
- Per le importazioni, sostituisci l'NDB e la coda di attività di App Engine con Cloud NDB e Pub/Sub.
- Rinomina
pullq
da un nomeQUEUE
a un nomeTOPIC
. - Con le attività pull, il worker le ha affittate per un'ora, ma con Pub/Sub i timeout vengono misurati in base ai singoli messaggi, quindi elimina la costante
HOUR
. - Le API Cloud richiedono l'utilizzo di un client API, quindi avviale per Cloud NDB e Cloud Pub/Sub, in modo che quest'ultimo fornisca i client sia per gli argomenti che per gli abbonamenti.
- Pub/Sub richiede l'ID progetto Cloud, quindi importalo e recuperalo da
google.auth.default()
. - Pub/Sub richiede "pathname completi" per argomenti e sottoscrizioni, quindi creali usando le funzioni di utilità di
*_path()
.
Di seguito sono riportate le importazioni e l'inizializzazione dal modulo 18, seguite dalle sezioni dopo l'implementazione delle modifiche descritte in precedenza, con la maggior parte del nuovo codice costituita da varie risorse Pub/Sub:
PRIMA:
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__)
DOPO:
from flask import Flask, render_template, request
import google.auth
from google.cloud import ndb, pubsub
LIMIT = 10
TASKS = 1000
TOPIC = 'pullq'
SBSCR = 'worker'
app = Flask(__name__)
ds_client = ndb.Client()
ppc_client = pubsub.PublisherClient()
psc_client = pubsub.SubscriberClient()
_, PROJECT_ID = google.auth.default()
TOP_PATH = ppc_client.topic_path(PROJECT_ID, TOPIC)
SUB_PATH = psc_client.subscription_path(PROJECT_ID, SBSCR)
Consulta gli aggiornamenti del modello dei dati
Il modello dei dati Visit
rimane invariato. L'accesso al datastore richiede l'uso esplicito del gestore di contesto del client API Cloud NDB, ds_client.context()
. Nel codice, questo significa che devi aggregare le chiamate Datastore in store_visit()
e fetch_visits()
all'interno dei blocchi with
Python. Questo aggiornamento è identico a quello trattato nel modulo 2.
La modifica più rilevante per Pub/Sub consiste nel sostituire l'accodamento di un'attività di pull della coda di attività con la pubblicazione di un messaggio Pub/Sub nell'argomento pullq
. Di seguito è riportato il codice prima e dopo questi aggiornamenti:
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 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)
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'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
ppc_client.publish(TOP_PATH, remote_addr.encode('utf-8'))
def fetch_visits(limit):
'get most recent visits'
with ds_client.context():
return Visit.query().order(-Visit.timestamp).fetch(limit)
Aggiornamenti del modello dei dati VisitorCount
Il modello dei dati VisitorCount
non cambia e utilizza fetch_counts()
, ad eccezione del wrapping della query Datastore all'interno di un blocco with
, come illustrato di seguito:
PRIMA:
class VisitorCount(ndb.Model):
visitor = ndb.StringProperty(repeated=False, required=True)
counter = ndb.IntegerProperty()
def fetch_counts(limit):
'get top visitors'
return VisitorCount.query().order(-VisitorCount.counter).fetch(limit)
DOPO:
class VisitorCount(ndb.Model):
visitor = ndb.StringProperty(repeated=False, required=True)
counter = ndb.IntegerProperty()
def fetch_counts(limit):
'get top visitors'
with ds_client.context():
return VisitorCount.query().order(-VisitorCount.counter).fetch(limit)
Aggiorna codice worker
Il codice worker si aggiorna per quanto riguarda la sostituzione di NDB con Cloud NDB e la coda di attività con Pub/Sub, ma il flusso di lavoro rimane lo stesso.
- Aggrega le chiamate Datastore nel blocco
with
del gestore di contesto Cloud NDB. - La pulizia della coda di attività comporta l'eliminazione di tutte le attività dalla coda di pull. Con Pub/Sub, gli "ID di conferma" vengono raccolti in
acks
e poi eliminati/confermati alla fine. - Le attività pull della coda di attività vengono noleggiate in modo simile al pull dei messaggi Pub/Sub. Mentre l'eliminazione delle attività pull viene eseguita con gli oggetti delle attività stessi, i messaggi Pub/Sub vengono eliminati tramite i relativi ID di conferma.
- I payload dei messaggi Pub/Sub richiedono byte (non stringhe Python), quindi sono previste alcune codifica e decodifica UTF-8 rispettivamente per la pubblicazione e il pull dei messaggi da un argomento.
Sostituisci log_visitors()
con il codice aggiornato riportato di seguito implementando le modifiche appena descritte:
PRIMA:
@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))
DOPO:
@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 = {}
acks = set()
rsp = psc_client.pull(subscription=SUB_PATH, max_messages=TASKS)
msgs = rsp.received_messages
for rcvd_msg in msgs:
acks.add(rcvd_msg.ack_id)
visitor = rcvd_msg.message.data.decode('utf-8')
tallies[visitor] = tallies.get(visitor, 0) + 1
if acks:
psc_client.acknowledge(subscription=SUB_PATH, ack_ids=acks)
try:
psc_client.close()
except AttributeError: # special handler for grpcio<1.12.0
pass
# increment those counts in Datastore and return
if tallies:
with ds_client.context():
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(msgs), len(tallies))
Non sono state apportate modifiche al gestore di applicazioni principale root()
. Non sono necessarie modifiche al file del modello HTML templates/index.html
, quindi vengono aggregati tutti gli aggiornamenti necessari. Congratulazioni per aver ricevuto la tua nuova applicazione del modulo 19 utilizzando Cloud Pub/Sub.
7. Riepilogo/Pulizia
Esegui il deployment dell'app per verificare che funzioni come previsto e in qualsiasi output riportato. Inoltre, esegui il worker 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à creato l'argomento pullq
e la sottoscrizione worker
. 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 all'app del Modulo 18, tranne per il fatto che hai sostituito l'intero meccanismo di accodamento sottostante:
Il frontend web dell'app ora verifica che questa parte dell'applicazione funzioni. Mentre questa parte dell'app esegue query e visualizza correttamente i visitatori principali e le visite più recenti, ricorda che l'app registra questa visita e crea un'attività pull per aggiungere questo visitatore al conteggio complessivo. L'attività è ora in coda, in attesa di essere elaborata.
Puoi eseguire questa operazione con un servizio di backend App Engine, un job cron
, passando a /log
o inviando una richiesta HTTP dalla riga di comando. Ecco un esempio di esecuzione e di chiamata al codice worker con curl
(sostituisci 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.
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:
- Diversi componenti di Cloud Pub/Sub hanno un Livello senza costi, Stabilisci l'utilizzo complessivo per avere un'idea migliore delle implicazioni in termini di costi e consulta la pagina dei prezzi per maggiori dettagli.
- Il servizio App Engine Datastore è fornito da Cloud Datastore (Cloud Firestore in modalità Datastore), che prevede anche un livello senza costi; consulta la pagina relativa ai prezzi per ulteriori informazioni.
Passaggi successivi
Oltre a questo tutorial, altri moduli di migrazione che si concentrano sull'abbandono dei servizi in bundle legacy da prendere in considerazione includono:
- Modulo 2: migrazione da App Engine
ndb
a Cloud NDB - Moduli 7-9: migrazione dalla coda di attività di App Engine (attività push) a Cloud Tasks
- Moduli 12-13: migrazione da App Engine Memcache a Cloud Memorystore
- Moduli 15-16: migrazione dal Blobstore di App Engine a Cloud Storage
App Engine non è più l'unica piattaforma serverless in Google Cloud. Se hai un'app App Engine di piccole dimensioni o con funzionalità limitate e vuoi convertirla in un microservizio autonomo oppure vuoi suddividere un'app monolitica in più componenti riutilizzabili, questi sono ottimi motivi per passare a Cloud Functions. Se la containerizzazione è diventata parte del flusso di lavoro per lo sviluppo delle applicazioni, in particolare se è costituita da una pipeline CI/CD (integrazione continua/distribuzione continua o deployment), valuta la possibilità di eseguire la migrazione a Cloud Run. Questi scenari sono trattati nei seguenti moduli:
- Eseguire la migrazione da App Engine a Cloud Functions: consulta il Modulo 11
- Esegui la migrazione da App Engine a Cloud Run: consulta il Modulo 4 per containerizzare la tua app con Docker oppure il Modulo 5 per eseguire questa operazione senza container, conoscenze di Docker o
Dockerfile
Il passaggio a un'altra piattaforma serverless è facoltativo e prima di apportare modifiche ti consigliamo di valutare le opzioni migliori per le tue app e i tuoi casi d'uso.
Indipendentemente dal modulo di migrazione successivo, sarà possibile accedere a tutti i contenuti di Serverless Migration Station (codelab, video, codice sorgente [se disponibile]) nel relativo repository open source. L'elemento README
del repository fornisce anche indicazioni sulle migrazioni da prendere in considerazione e su eventuali "ordine" pertinenti dei Moduli di migrazione.
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 dei 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 18 (START) e il modulo 19 (FINISH) sono disponibili nella tabella seguente.
Codelab | Python 2 | Python 3 |
(n/d) | ||
Modulo 19 (questo codelab) | (Come per Python 2, tranne per l'uso di app3.yaml, a meno che tu non abbia aggiornato app.yaml come descritto sopra) |
Riferimenti online
Di seguito sono riportate le risorse pertinenti per questo tutorial:
Coda di attività App Engine
- Panoramica della coda di attività di App Engine
- Panoramica delle code di pull delle code di attività di App Engine
- App di esempio completa della coda di pull della coda di attività di App Engine
- Creazione di code di pull delle code di attività
- Video sul lancio della coda di pull di Google I/O 2011 ( app di esempio Votatore)
- Riferimento
queue.yaml
- Confronto tra
queue.yaml
e Cloud Tasks - Guida alla migrazione delle code in modalità pull a Pub/Sub
Cloud Pub/Sub
- Pagina del prodotto Cloud Pub/Sub
- Utilizzo delle librerie client di Pub/Sub
- Esempi di librerie client Python di Pub/Sub
- Documentazione sulla libreria client Python di Pub/Sub
- Crea e gestisci gli argomenti Pub/Sub
- Linee guida per la denominazione degli argomenti Pub/Sub
- Crea e gestire le sottoscrizioni Pub/Sub
- App di esempio (flessibile) di App Engine (disponibile anche per la versione Standard; Python 3)
- Repository per l'app di esempio sopra riportata
- Sottoscrizioni al pull Pub/Sub
- Sottoscrizioni push di Pub/Sub
- App di esempio push di Pub/Sub di App Engine (Python 3)
- Repository di app di esempio per il push di App Engine Pub/Sub
- Informazioni sui prezzi di Pub/Sub
- Cloud Tasks o Cloud Pub/Sub? (push e pull)
NDB di App Engine e Cloud NDB (Datastore)
- Documentazione su App Engine NDB
- Repository NDB di App Engine
- Documentazione su NDB di Google Cloud
- Repository NDB di Google Cloud
- Informazioni sui prezzi di Cloud Datastore
Piattaforma App Engine
- Documentazione di App Engine
- Runtime Python 2 App Engine (ambiente standard)
- Utilizzo delle librerie integrate di App Engine in App Engine per Python 2
- 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)
- Confronto tra primo e piattaforme di seconda generazione
- Assistenza a lungo termine per i runtime legacy
- Esempi di migrazione della documentazione
- Esempi di migrazione forniti dalla community
Altre informazioni sul cloud
- Python su Google Cloud Platform
- Librerie client di Google Cloud per Python
- "Sempre senza costi" di Google Cloud livello
- Google Cloud SDK (strumento a riga di comando
gcloud
) - Tutta la documentazione di Google Cloud
Video
- Stazione di migrazione serverless
- Esplorazioni serverless
- Iscriviti a Google Cloud Tech
- Iscriviti a Google Developers
Licenza
Questo lavoro è concesso in licenza ai sensi di una licenza Creative Commons Attribution 2.0 Generic.