1. Panoramica
Questa serie di codelab (tutorial pratici e self-service) ha lo scopo di aiutare gli sviluppatori di Google App Engine (ambiente standard) a modernizzare le loro app, guidandoli attraverso una serie di migrazioni. Il passaggio più significativo è abbandonare i servizi originali in bundle per il runtime perché i runtime di nuova generazione sono più flessibili e offrono agli utenti una maggiore varietà di opzioni di servizi. Il passaggio al runtime di nuova generazione consente un'integrazione più semplice con i prodotti Google Cloud, l'utilizzo di una gamma più ampia di servizi supportati e il supporto delle release nelle lingue attuali.
Questo tutorial facoltativo mostra agli sviluppatori come eseguire la migrazione da Cloud NDB a Cloud Datastore come libreria client per comunicare con il servizio Datastore. Poiché è compatibile con Python 3, gli sviluppatori che preferiscono NDB possono continuare a utilizzarla, perciò questa migrazione è facoltativa. Questa migrazione è rivolta solo a chi vuole creare un codebase coerente e librerie condivise con altre app che già utilizzano Cloud Datastore. Questa procedura è spiegata nella sezione .
Imparerai a
- Usa Cloud NDB (se non hai familiarità)
- Migrazione da Cloud NDB a Cloud Datastore
- Esegui ulteriormente la migrazione dell'app a Python 3
Che cosa ti serve
- Un progetto Google Cloud Platform con un account di fatturazione Google Cloud attivo
- Competenze Python di base
- Conoscenza pratica dei comandi di base Linux
- Conoscenza di base dello sviluppo e del deployment delle app App Engine
- Un'app App Engine 2.x o 3.x del Modulo 2 funzionante.
Sondaggio
Come utilizzerai questo codelab?
2. Sfondo
Sebbene Cloud NDB sia un'ottima soluzione Datastore per gli sviluppatori di App Engine di lunga data e aiuti il passaggio a Python 3, non è l'unico modo in cui gli sviluppatori di App Engine possono accedere a Datastore. Quando Datastore di App Engine è diventato un prodotto proprietario nel 2013, Google Cloud Datastore, è stata creata una nuova libreria client in modo che tutti gli utenti possano utilizzare Datastore.
Gli sviluppatori Python 3 di App Engine e non App Engine sono invitati a utilizzare Cloud Datastore (non Cloud NDB). Gli sviluppatori App Engine in Python 2 sono invitati a eseguire la migrazione da ndb
a Cloud NDB e alla porta a Python 3 da lì, ma possono anche scegliere di eseguire ulteriormente la migrazione a Cloud Datastore. Si tratta di una decisione logica, in particolare per gli sviluppatori che hanno già codice che utilizza Cloud Datastore, come quelli appena menzionati, e vogliono creare librerie condivise in tutte le loro applicazioni. Il riutilizzo del codice è una best practice, così come la coerenza del codice, ed entrambe contribuiscono alla riduzione complessiva dei costi di manutenzione, come riepilogato di seguito:
Migrazione da Cloud NDB a Cloud Datastore
- Consente agli sviluppatori di concentrarsi su un singolo codebase per l'accesso a Datastore
- Evita di mantenere parte del codice utilizzando Cloud NDB e altri utilizzando Cloud Datastore
- Fornisce maggiore coerenza nel codebase e migliore riutilizzabilità del codice
- Consente l'utilizzo di librerie comuni/condivise, che contribuiscono a ridurre i costi di manutenzione complessivi
Questa migrazione prevede i seguenti passaggi principali:
- Configurazione/pre-lavoro
- Sostituisci Cloud NDB con le librerie client di Cloud Datastore
- Aggiorna applicazione
3. Configurazione/pre-lavoro
Prima di proseguire con la parte principale del tutorial, impostiamo il progetto, recuperiamo il codice ed eseguiamo il deployment dell'app di base in modo da sapere di aver iniziato con il codice funzionante.
1. Configura il progetto
Se hai completato il codelab del Modulo 2, ti consigliamo di riutilizzare lo stesso progetto (e lo stesso codice). In alternativa, puoi creare un nuovo progetto o riutilizzare un altro progetto esistente. Assicurati che il progetto abbia un account di fatturazione attivo e che App Engine (app) sia abilitato.
2. Ottieni app di esempio di riferimento
Uno dei prerequisiti è avere un'app di esempio del Modulo 2 funzionante. Utilizza la tua soluzione se hai completato il tutorial. Puoi completarlo ora (link sopra) oppure, se vuoi saltarlo, quindi copia il repository del modulo 2 (link di seguito).
Che tu usi il tuo o il nostro codice, iniziamo dal Modulo 2. Questo codelab del modulo 3 illustra ogni passaggio e, una volta completato, dovrebbe assomigliare al codice nel punto FINISH. Esistono versioni Python 2 e 3 di questo tutorial, quindi recupera il repository di codice corretto di seguito.
Python 2
- AVVIO: Codice del Modulo 2
- FINISH: Codice del Modulo 3
- Intero repository (per clonare o scaricare il file ZIP)
La directory dei file Python 2 del Modulo 2 AVVIO (tuoi o nostri) dovrebbe avere questo aspetto:
$ ls
README.md appengine_config.py requirements.txt
app.yaml main.py templates
Se hai completato il tutorial del modulo 2, avrai anche una cartella lib
con Flask e le sue dipendenze. Se non hai una cartella lib
, creala con il comando pip install -t lib -r requirements.txt
in modo da poter eseguire il deployment di questa app di base nel passaggio successivo. Se hai installato Python 2 e 3, ti consigliamo di utilizzare pip2
anziché pip
per evitare confusione con Python 3.
Python 3
- AVVIA: repository del Modulo 2
- FINISH: Repository del Modulo 3
- Intero repository (per clonare o scaricare il file ZIP)
La directory dei file Python 3 del Modulo 2 AVVIO (tuoi o nostri) dovrebbe avere questo aspetto:
$ ls
README.md main.py templates
app.yaml requirements.txt
Non vengono utilizzati né lib
né appengine_config.py
per Python 3.
3. (Ri)Esegui il deployment dell'app del Modulo 2
I passaggi preliminari rimanenti da eseguire ora:
- Acquisisci familiarità con lo strumento a riga di comando
gcloud
(se necessario) - (Ri)eseguire il deployment del codice del Modulo 1 in App Engine (se necessario).
Dopo aver eseguito correttamente questi passaggi e aver confermato che è operativo, proseguiremo con questo tutorial, iniziando con i file di configurazione.
4. Sostituisci Cloud NDB con le librerie client di Cloud Datastore
L'unica modifica alla configurazione è un piccolo scambio di pacchetti nel file requirements.txt
.
1. Aggiorna requirements.txt
Dopo aver completato il modulo 2, il tuo file requirements.txt
aveva il seguente aspetto:
- PRIMA (Python 2 e 3):
Flask==1.1.2
google-cloud-ndb==1.7.1
Aggiorna requirements.txt
sostituendo la libreria Cloud NDB (google-cloud-ndb
) con la versione più recente della libreria Cloud Datastore (google-cloud-datastore
), lasciando invariata la voce Flask, tenendo presente che la versione finale di Cloud Datastore compatibile con Python 2 è la 1.15.3:
- DOPO (Python 2):
Flask==1.1.2
google-cloud-datastore==1.15.3
- DOPO (Python 3):
Flask==1.1.2
google-cloud-datastore==2.1.0
Tieni presente che il repository viene gestito più regolarmente rispetto a questo tutorial, quindi è possibile che il file requirements.txt
rifletta versioni più recenti. Consigliamo di utilizzare le versioni più recenti di ogni libreria, ma se non funzionano, puoi eseguire il rollback a una release precedente. I numeri di versione sopra riportati sono quelli più recenti a partire dall'ultimo aggiornamento di questo codelab.
2. Altri file di configurazione
Gli altri file di configurazione, app.yaml
e appengine_config.py
, non subiranno modifiche rispetto al passaggio precedente della migrazione:
app.yaml
deve (ancora) fare riferimento ai pacchetti di terze partigrpcio
esetuptools
.appengine_config.py
deve (ancora) indirizzarepkg_resources
egoogle.appengine.ext.vendor
alle risorse di terze parti inlib
.
Ora passiamo ai file dell'applicazione.
5. Aggiorna i file dell'applicazione
Nessuna modifica a template/index.html
, ma ci sono alcuni aggiornamenti per main.py
.
1. Importazioni
Il codice iniziale per la sezione di importazione dovrebbe avere il seguente aspetto:
- PRIMA:
from flask import Flask, render_template, request
from google.cloud import ndb
Sostituisci l'importazione google.cloud.ndb
con una per Cloud Datastore: google.cloud.datastore
. Poiché la libreria client Datastore non supporta la creazione automatica di un campo timestamp in un'entità, importa anche il modulo datetime
della libreria standard per crearne uno manualmente. Per convenzione, le importazioni standard della libreria sono superiori a quelle dei pacchetti di terze parti. Una volta apportate queste modifiche, il codice dovrebbe avere il seguente aspetto:
- DOPO:
from datetime import datetime
from flask import Flask, render_template, request
from google.cloud import datastore
2. Inizializzazione e modello dei dati
Dopo aver inizializzato Flask, l'app di esempio del modulo 2 che crea una classe di modello dei dati NDB e i suoi campi funzionano come segue:
- PRIMA:
app = Flask(__name__)
ds_client = ndb.Client()
class Visit(ndb.Model):
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
La libreria Cloud Datastore non dispone di una classe di questo tipo, quindi elimina la dichiarazione della classe Visit
. Hai ancora bisogno di un client per comunicare con Datastore, quindi modifica ndb.Client()
in datastore.Client()
. La libreria Datastore è più "flessibile", che ti consente di creare entità senza fare "pre-dichiarazione" con una struttura simile a NDB. Dopo questo aggiornamento, questa parte di main.py
dovrebbe avere il seguente aspetto:
- DOPO:
app = Flask(__name__)
ds_client = datastore.Client()
3. Accesso a Datastore
La migrazione a Cloud Datastore richiede la modifica del modo in cui crei, archivi ed esegui query sulle entità Datastore (a livello di utente). Per le tue applicazioni, la difficoltà di questa migrazione dipende dalla complessità del codice Datastore. Nella nostra app di esempio, abbiamo cercato di rendere l'aggiornamento il più semplice possibile. Ecco il nostro codice di partenza:
- PRIMA:
def store_visit(remote_addr, user_agent):
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
def fetch_visits(limit):
with ds_client.context():
return (v.to_dict() for v in Visit.query().order(
-Visit.timestamp).fetch_page(limit)[0])
Con Cloud Datastore, puoi creare un'entità generica, identificando con una "chiave" gli oggetti raggruppati nell'entità. Crea il record di dati con un oggetto JSON (Python dict
) di coppie chiave-valore, quindi scrivilo in Datastore con il put()
previsto. L'esecuzione di query in Datastore è simile ma più diretta. Di seguito puoi vedere le differenze tra il codice Datastore equivalente:
- DOPO:
def store_visit(remote_addr, user_agent):
entity = datastore.Entity(key=ds_client.key('Visit'))
entity.update({
'timestamp': datetime.now(),
'visitor': '{}: {}'.format(remote_addr, user_agent),
})
ds_client.put(entity)
def fetch_visits(limit):
query = ds_client.query(kind='Visit')
query.order = ['-timestamp']
return query.fetch(limit=limit)
Aggiorna il corpo delle funzioni per store_visit()
e fetch_visits()
come indicato in precedenza, mantenendo le relative firme identiche alla versione precedente. Non sono state apportate modifiche al gestore principale root()
. Dopo aver completato queste modifiche, l'app è pronta per utilizzare Cloud Datastore ed è pronta per essere test.
6. Riepilogo/Pulizia
Esegui il deployment di un'applicazione
Esegui di nuovo il deployment dell'app con gcloud app deploy
e verifica che funzioni. Il codice dovrebbe corrispondere ora al contenuto delle cartelle dei repository del modulo 3:
Se hai seguito questa serie senza aver eseguito nessuno dei codelab precedenti, l'app in sé non cambierà: vengono registrate tutte le visite alla pagina web principale (/
) e si presenta come questa una volta che hai visitato il sito un numero sufficiente di volte:
Congratulazioni per aver completato il codelab del Modulo 3. Ora sai che puoi utilizzare entrambe le librerie client di Cloud NDB e Cloud Datastore per accedere a Datastore. Eseguendo la migrazione a quest'ultima, ora puoi usufruire delle librerie condivise, del codice comune e del riutilizzo del codice per coerenza e costi di manutenzione ridotti.
(Facoltativo) Eseguire la pulizia
Che ne dici di eseguire la pulizia per evitare di ricevere addebiti finché non decidi di passare al codelab di migrazione successivo? In qualità di sviluppatori esistenti, probabilmente sei già al passo con le informazioni sui prezzi di App Engine.
(Facoltativo) Disattiva l'app
Se non vuoi ancora passare al prossimo tutorial, disattiva la tua app per evitare che ti vengano addebitati dei costi. Quando vuoi passare al codelab successivo, puoi riabilitarlo. Mentre l'app è disabilitata, non riceverà traffico che comporta addebiti, ma un'altra cosa che ti può essere fatturata è l'utilizzo di Datastore se supera la quota senza costi, quindi eliminane un numero sufficiente per rientrare nel limite.
Se invece non intendi continuare con le migrazioni e vuoi eliminare tutto il tutto, puoi chiudere il progetto.
Passaggi successivi
Da qui, puoi esplorare i prossimi moduli di migrazione:
- Bonus Modulo 3: passa alla sezione relativa ai bonus per scoprire come trasferire Python 3 e il runtime di App Engine di nuova generazione.
- Modulo 7: Code di attività push di App Engine (obbligatorie se utilizzi le code di attività [push])
- Aggiunge attività push di
taskqueue
di App Engine all'app del modulo 1 - Prepara gli utenti alla migrazione a Cloud Tasks nel modulo 8
- Aggiunge attività push di
- Modulo 4: Esegui la migrazione a Cloud Run con Docker
- Containerizza la tua app per eseguirla su Cloud Run con Docker
- Consente di rimanere su Python 2
- Modulo 5: Esegui la migrazione a Cloud Run con Cloud Buildpacks
- Containerizza la tua app per eseguirla su Cloud Run con Cloud Buildpacks
- Non hanno bisogno di sapere nulla su Docker, container o
Dockerfile
- Richiede che tu abbia già eseguito la migrazione della tua app a Python 3
- Modulo 6: Esegui la migrazione a Cloud Firestore
- Esegui la migrazione a Cloud Firestore per accedere alle funzionalità di Firebase
- Sebbene Cloud Firestore supporti Python 2, questo codelab è disponibile solo in Python 3.
7. BONUS: migrazione a Python 3
Per accedere al runtime e alle funzionalità più recenti di App Engine, ti consigliamo di eseguire la migrazione a Python 3. Nella nostra app di esempio, Datastore era l'unico servizio integrato che abbiamo utilizzato e, poiché abbiamo eseguito la migrazione da ndb
a Cloud NDB, ora possiamo eseguire il trasferimento al runtime Python 3 di App Engine.
Panoramica
Sebbene la portabilità a Python 3 non rientri nell'ambito di un tutorial di Google Cloud, questa parte del codelab offre agli sviluppatori un'idea delle differenze tra il runtime di App Engine per Python 3. Una funzionalità eccezionale del runtime di nuova generazione è l'accesso semplificato ai pacchetti di terze parti: non è necessario specificare i pacchetti integrati in app.yaml
né il requisito di copiare o caricare librerie non integrate; sono installate implicitamente e non sono elencate in requirements.txt
.
Poiché il nostro esempio è molto basilare e Cloud Datastore è compatibile con Python 2-3, non è necessario trasferire esplicitamente il codice dell'applicazione a 3.x: l'app viene eseguita su 2.x e 3.x senza modifiche. In questo caso, le uniche modifiche richieste sono nella configurazione:
- Semplifica
app.yaml
in modo che faccia riferimento a Python 3 e rimuovi il riferimento alle librerie di terze parti in bundle. - Elimina
appengine_config.py
e la cartellalib
perché non sono più necessarie.
I file dell'applicazione main.py
e templates/index.html
rimangono invariati.
Aggiorna requirements.txt
La versione finale di Cloud Datastore che supporta Python 2 è la 1.15.3. Aggiorna requirements.txt
con l'ultima versione per Python 3 (ora potrebbe essere più recente). Quando è stato scritto questo tutorial, l'ultima versione era la 2.1.0, quindi modifica la riga in modo che abbia questo aspetto (o qualunque sia la versione più recente):
google-cloud-datastore==2.1.0
Semplifica app.yaml
PRIMA:
L'unica modifica reale per questa app di esempio è la riduzione significativa di app.yaml
. A titolo di promemoria, ecco cosa abbiamo fatto nel app.yaml
alla conclusione del modulo 3:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: grpcio
version: 1.0.0
- name: setuptools
version: 36.6.0
DOPO:
In Python 3, le istruzioni threadsafe
, api_version
e libraries
sono tutte deprecate; tutte le app sono presunte come threadsafe e api_version
non è utilizzato in Python 3. Non ci sono più pacchetti di terze parti integrati preinstallati nei servizi App Engine, quindi anche libraries
è deprecato. Per saperne di più su queste modifiche, consulta la documentazione sulle modifiche apportate a app.yaml
. Di conseguenza, dovresti eliminare tutti e tre da app.yaml
ed eseguire l'aggiornamento a una versione Python 3 supportata (vedi sotto).
Facoltativo: utilizzo dell'istruzione handlers
Inoltre, è stata deprecata anche l'istruzione handlers
, che indirizza il traffico alle applicazioni App Engine. Poiché il runtime di nuova generazione prevede che i framework web gestiscano il routing delle app, tutti gli "script handle" deve essere modificato in "auto
". Combinando le modifiche di cui sopra, ottieni questo app.yaml
:
runtime: python38
handlers:
- url: /.*
script: auto
Scopri di più su script: auto
dalla pagina di riferimento di app.yaml
.
Rimozione istruzione handlers
in corso...
Poiché handlers
è deprecato, puoi rimuovere anche l'intera sezione lasciando un elemento app.yaml
di una sola riga:
runtime: python38
Per impostazione predefinita, verrà avviato il server web WSGI di Gunicorn, disponibile per tutte le applicazioni. Se conosci gunicorn
, questo è il comando eseguito quando viene avviato per impostazione predefinita con le app.yaml
:
gunicorn main:app --workers 2 -c /config/gunicorn.py
Facoltativo: utilizzo dell'istruzione entrypoint
Se, tuttavia, l'applicazione richiede un comando di avvio specifico, che può essere specificato con un'istruzione entrypoint
, generando un valore app.yaml
simile al seguente:
runtime: python38
entrypoint: python main.py
In questo esempio, in particolare, viene richiesto l'utilizzo del server di sviluppo Flask al posto di gunicorn
. Inoltre, il codice che avvia il server di sviluppo deve essere aggiunto all'app per essere lanciato sull'interfaccia 0.0.0.0
sulla porta 8080 aggiungendo questa piccola sezione in fondo a main.py
:
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080, debug=True)
Scopri di più su entrypoint
dalla pagina di riferimento di app.yaml
. Ulteriori esempi e best practice sono disponibili nei documenti per le startup nell'ambiente standard di App Engine e nei documenti per le startup sull'ambiente flessibile di App Engine.
Elimina appengine_config.py
e lib
Elimina il file appengine_config.py
e la cartella lib
. Nella migrazione a Python 3, App Engine acquisisce e installa i pacchetti elencati in requirements.txt
.
Il file di configurazione appengine_config.py
viene utilizzato per riconoscere librerie/pacchetti di terze parti, sia che tu li abbia copiati personalmente sia che utilizzi quelli già disponibili sui server App Engine (integrati). Quando passi a Python 3, un riepilogo dei grandi cambiamenti sono:
- Nessun raggruppamento di librerie di terze parti copiate (elencate in
requirements.txt
) - Nessun
pip install
in una cartellalib
, il che significa che nessun punto della cartellalib
- Nessun elenco delle librerie di terze parti integrate in
app.yaml
- Non è necessario fare riferimento all'app a librerie di terze parti, quindi nessun file
appengine_config.py
Tutto ciò che serve è elencare tutte le librerie di terze parti obbligatorie in requirements.txt
.
Esegui il deployment di un'applicazione
Esegui di nuovo il deployment dell'app per assicurarti che funzioni. Puoi anche confermare quanto la tua soluzione è vicina al codice Python 3 di esempio del Modulo 3. Per visualizzare le differenze con Python 2, confronta il codice con la sua versione Python 2.
Congratulazioni per aver completato il passaggio bonus del modulo 3. Consulta la documentazione sulla preparazione dei file di configurazione per il runtime di Python 3. Infine, rivedi il riepilogo precedente sopra per i passaggi successivi e la pulizia.
Preparazione della tua richiesta
Al momento di eseguire la migrazione della tua applicazione, devi trasferire i file main.py
e di altre applicazioni alla versione 3.x, quindi una best practice è fare del tuo meglio per rendere la tua applicazione 2.x "compatibile con il protocollo" il più possibile.
Esistono numerose risorse online per raggiungere questo obiettivo, ma ecco alcuni suggerimenti chiave:
- Assicurati che tutte le dipendenze dell'applicazione siano completamente compatibili con 3.x
- Assicurati che l'applicazione venga eseguita su almeno 2.6 (preferibilmente 2.7)
- Assicurati che l'applicazione superi l'intera suite di test (e almeno l'80% di copertura)
- Utilizza librerie di compatibilità come
six
, Future e/o Modernize - Informati sulle differenze chiave tra 2.x e 3.x incompatibili con le versioni precedenti
- Qualsiasi I/O probabilmente genererà incompatibilità con Unicode rispetto alle stringhe di byte
L'app di esempio è stata progettata tenendo conto di tutto questo, ecco perché l'app funziona subito su 2.x e 3.x, così possiamo concentrarci a mostrarti cosa deve essere cambiato per utilizzare la piattaforma di nuova generazione.
8. Risorse aggiuntive
Problemi/feedback dei codelab per i moduli di migrazione di App Engine
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 2 (START) e il modulo 3 (FINISH) sono disponibili nella tabella seguente. Sono inoltre accessibili dal repository per tutte le migrazioni di App Engine che puoi clonare o scaricare un file ZIP.
Codelab | Python 2 | Python 3 |
Module 3 |
Risorse App Engine
Di seguito sono riportate ulteriori risorse relative a questa specifica migrazione:
- Riferimenti per Python Cloud NDB e Cloud Datastore
- Migrazione a Python 3 e al runtime di nuova generazione di GAE
- Generale