Modulo 2: Migrazione da App Engine ndb a Cloud NDB

1. Panoramica

Questa serie di codelab (tutorial pratici e self-service) mira ad aiutare gli sviluppatori di Google App Engine (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 insegna come eseguire la migrazione dalla libreria client ndb (Next Database) integrata di App Engine alla libreria client Cloud NDB.

Imparerai a

  • Utilizzare la libreria ndb di App Engine (se non la conosci)
  • Esegui la migrazione da ndb a Cloud NDB
  • Esegui ulteriormente la migrazione dell'app a Python 3

Che cosa ti serve

Sondaggio

Come utilizzerai questo codelab?

Da leggere solo Leggilo e completa gli esercizi

2. Sfondo

Nel modulo 1, abbiamo eseguito la migrazione dei framework web dalla tecnologia webapp2 integrata di App Engine a Flask. In questo codelab, continuiamo ad abbandonare i servizi integrati di App Engine passando dalla libreria ndb di App Engine a Google Cloud NDB.

Completando la migrazione potrai:

  1. Esegui la migrazione a Python 3 e al runtime di App Engine di nuova generazione
  2. Migrazione a Cloud Datastore (libreria client per le app non App Engine)
  3. Containerizza la tua app Python 2 (o 3) ed esegui la migrazione a Cloud Run
  4. Aggiungi l'utilizzo delle code di attività di App Engine (push), quindi esegui la migrazione a Cloud Tasks

Ma non ci siamo ancora. Termina questo codelab prima di considerare i passaggi successivi. La migrazione di questo tutorial presenta i seguenti passaggi principali:

  1. Configurazione/pre-lavoro
  2. Aggiungi libreria Cloud NDB
  3. Aggiorna i file dell'applicazione

3. Configurazione/pre-lavoro

Prima di passare alla parte principale del tutorial, configuriamo il progetto, recuperiamo il codice ed eseguiamo il deployment dell'app di base per sapere di aver iniziato con il codice funzionante.

1. Configura il progetto

Se hai completato il codelab del Modulo 1, 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 sia abilitato.

2. Ottieni app di esempio di riferimento

Uno dei prerequisiti è avere un'app di esempio del Modulo 1 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 1 (link di seguito).

Che tu usi il tuo o il nostro, il codice del Modulo 1 è il punto di partenza. Questo codelab del Modulo 2 illustra ogni passaggio e, una volta completato, dovrebbe assomigliare al codice nel punto FINISH (inclusa una porta "bonus" facoltativa da Python 2 a 3):

La cartella di codice STARTing Module 1 dovrebbe contenere i seguenti contenuti:

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

Se hai completato il tutorial del modulo 1, 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.

3. (Ri)Esegui il deployment dell'app del Modulo 1

I passaggi preliminari rimanenti da eseguire ora:

  1. Acquisisci familiarità con lo strumento a riga di comando gcloud (se necessario)
  2. (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. Aggiorna i file di configurazione (aggiungi la libreria Cloud NDB)

Molti servizi integrati originali di App Engine sono sbocciati nei propri prodotti e Datastore è uno di questi. Attualmente le app non App Engine possono utilizzare Cloud Datastore. Per gli utenti di ndb di lunga data, il team di Google Cloud ha creato la libreria client Cloud NDB per comunicare con Cloud Datastore. È disponibile sia per Python 2 che per 3.

Aggiorniamo i file di conferma per sostituire App Engine ndb con Cloud NDB, quindi modifichiamo la nostra applicazione.

1. Aggiorna requirements.txt

Nel modulo 1, l'unica dipendenza esterna per la nostra app era Flask. Ora aggiungiamo Cloud NDB. Ecco come era il tuo file requirements.txt alla fine del modulo 1:

  • PRIMA:
Flask==1.1.2

La migrazione da App Engine ndb richiede la libreria Cloud NDB (google-cloud-ndb), quindi aggiungi il relativo pacchetto a requirements.txt.

  • DOPO:
Flask==1.1.2
google-cloud-ndb==1.7.1

Quando è stato scritto questo codelab, l'ultima versione consigliata è la 1.7.1, ma requirements.txt nel repository potrebbe avere una versione più recente. Consigliamo le versioni più recenti di ogni libreria, ma se non funzionano, puoi eseguire il rollback a una release precedente.

Elimina la tua cartella lib se ne hai una e non l'hai appena creata sopra. Ora (re)installa le librerie aggiornate con il comando pip install -t lib -r requirements.txt, utilizzando pip2 anziché pip se necessario.

2. Aggiorna app.yaml

L'aggiunta di librerie client di Google Cloud come google-cloud-ndb prevede alcuni requisiti, che riguardano tutti l'inclusione del componente "integrato" librerie, pacchetti di terze parti già disponibili sui server Google. Non li elenchi in requirements.txt né li copi con pip install. Gli unici requisiti:

  1. Specifica le librerie integrate in app.yaml
  2. Indirizzali alle librerie di terze parti copiate con cui potrebbero lavorare (in lib)

Ecco il app.yaml INIZIALE del modulo 1:

  • PRIMA:
runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

Ora aggiungi le seguenti righe a app.yaml per fare riferimento a una coppia di pacchetti di terze parti in bundle: grpcio e setuptools in una nuova sezione libraries:

libraries:
- name: grpcio
  version: 1.0.0
- name: setuptools
  version: 36.6.0

Perché usare queste librerie integrate? gRPC è un framework RPC aperto utilizzato da tutte le librerie client di Google Cloud, tra cui google-cloud-ndb. La libreria grpcio è l'adattatore gRPC Python e quindi è obbligatoria. Il ragionamento per includere setuptools è in arrivo.

  • DOPO:

Con le modifiche riportate sopra, il valore app.yaml aggiornato ora dovrebbe avere il seguente aspetto:

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

3. Aggiorna appengine_config.py

Lo strumento pkg_resources, parte della libreria setuptools, viene utilizzato per consentire alle librerie di terze parti integrate di accedere a quelle in bundle. Aggiorna appengine_config.py per utilizzare pkg_resources che indirizzi alle librerie incluse nel bundle in lib. Una volta completata la modifica, l'intero file dovrebbe avere il seguente aspetto:

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)

5. Aggiorna i file dell'applicazione

Eliminando le formalità dei file di configurazione, ora puoi eseguire la migrazione da ndb a Cloud NDB. Per completare la migrazione, aggiorna le librerie importate e aggiungi l'utilizzo della gestione del contesto in main.py.

1. Importazioni

Effettua il seguente scambio di importazione in main.py:

  • PRIMA
from google.appengine.ext import ndb
  • DOPO:
from google.cloud import ndb

Il passaggio da una libreria App Engine a una libreria Google Cloud a volte è discreto come questa istanza. Per i servizi integrati che sono diventati prodotti Google Cloud completi, importerai gli attributi da google.cloud anziché da google.appengine.

2. Accesso a Datastore

Per poter utilizzare la libreria Cloud NDB, l'app deve utilizzare gestori di contesto Python. Il loro scopo è "gateway" l'accesso alle risorse, in modo che debbano essere acquisite prima di poter essere utilizzate. I gestori del contesto si basano su una tecnica di controllo informatica nota come l'allocazione delle risorse è inizializzazione (o RAII). I gestori del contesto vengono utilizzati con i file Python (che devono essere aperti prima di potervi accedere) e con la contemporaneità, "spin Locks" deve essere acquisito prima del codice in una "sezione critica" eseguire il deployment.

Allo stesso modo, Cloud NDB richiede di acquisire il contesto di un client per comunicare con Datastore prima dell'esecuzione di qualsiasi comando Datastore. Innanzitutto, crea un client (ndb.Client()) aggiungendo ds_client = ndb.Client() in main.py subito dopo l'inizializzazione di Flask:

app = Flask(__name__)
ds_client = ndb.Client()

Il comando Pythonwith viene utilizzato esclusivamente per ottenere il contesto di un oggetto. Aggrega eventuali blocchi di codice che accedono a Datastore con le istruzioni with.

Di seguito sono riportate le stesse funzioni del Modulo 1 per la scrittura di una nuova entità in Datastore e per la visualizzazione delle entità aggiunte più di recente:

  • PRIMA:

Ecco il codice originale senza gestione del contesto:

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 (v.to_dict() for v in Visit.query().order(
            -Visit.timestamp).fetch(limit))
  • DOPO:

Ora aggiungi with ds_client.context(): e sposta il codice di accesso Datastore nel blocco with:

def store_visit(remote_addr, user_agent):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

def fetch_visits(limit):
    'get most recent visits'
    with ds_client.context():
        return (v.to_dict() for v in Visit.query().order(
                -Visit.timestamp).fetch(limit))

L'applicazione driver principale rimane identica a quella del modulo 1, in quanto qui non c'è alcun codice ndb (né Cloud NDB):

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

Una best practice consiste nel garantire una chiara distinzione tra codice dell'applicazione e accesso ai dati. In questo modo, il codice dell'applicazione principale non cambia se il meccanismo di archiviazione dei dati sottostante viene alterato come abbiamo fatto con questa migrazione.

6. Riepilogo/Pulizia

Esegui il deployment di un'applicazione

Esegui di nuovo il deployment dell'app con gcloud app deploy e verifica che funzioni. Ora il codice dovrebbe corrispondere al contenuto del repository del Modulo 2.

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:

app visitme

Congratulazioni per aver completato il codelab del Modulo 2. Hai appena tagliato il traguardo, poiché questa è l'ultima delle migrazioni vivamente consigliate di questa serie per quanto riguarda Datastore.

(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, c'è una certa flessibilità per la tua prossima mossa. Scegli una di queste opzioni:

  • Bonus del Modulo 2: continua con la parte bonus di questo tutorial per esplorare la portabilità a Python 3 e al 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
  • 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 devi sapere nulla su Docker, container o Dockerfile
    • Richiede che tu abbia già eseguito la migrazione della tua app a Python 3
  • Modulo 3:
    • Modernizza l'accesso a Datastore da Cloud NDB a Cloud Datastore
    • Questa è la libreria utilizzata per le app App Engine e Python 3 e non App Engine

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 caratteristica eccezionale del runtime di nuova generazione è l'accesso semplificato ai pacchetti di terze parti; non è necessario specificare pacchetti integrati in app.yaml né è necessario copiare o caricare librerie non integrate; sono installate implicitamente e non sono elencate in requirements.txt.

Poiché il nostro esempio è molto basilare e Cloud NDB è 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, il che significa che le uniche modifiche richieste sono in fase di configurazione in questo caso:

  1. Semplifica app.yaml in modo che faccia riferimento a Python 3 e rimuovi le librerie di terze parti.
  2. Elimina appengine_config.py e la cartella lib perché non sono più necessarie.

Oltre a main.py, i file requirements.txt e templates/index.html rimangono invariati.

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 2:

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 nella pagina della documentazione.

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, dove app.yaml avrà il seguente aspetto:

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 nella pagina della documentazione corrispondente. Altri esempi e best practice sono disponibili nei documenti per l'avvio dell'ambiente standard di App Engine e nei documenti per l'avvio relativi all'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:

  1. Nessun raggruppamento di librerie di terze parti copiate (elencate in requirements.txt)
  2. Nessun pip install in una cartella lib, il che significa che nessun punto della cartella lib
  3. Nessun elenco delle librerie di terze parti integrate in app.yaml
  4. 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 2. 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 2. Consulta la documentazione sulla preparazione dei file di configurazione per il runtime di Python 3. Infine, consulta la pagina Riepilogo/Pulizia (precedente) 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:

  1. Assicurati che tutte le dipendenze dell'applicazione siano completamente compatibili con 3.x
  2. Assicurati che l'applicazione venga eseguita su almeno 2.6 (preferibilmente 2.7)
  3. Assicurati che l'applicazione superi l'intera suite di test (e almeno l'80% di copertura)
  4. Utilizza librerie di compatibilità come six, Future e/o Modernize
  5. Informati sulle differenze chiave tra 2.x e 3.x incompatibili con le versioni precedenti
  6. 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 1 (START) e il modulo 2 (FINISH) sono disponibili nella tabella seguente. Sono inoltre accessibili dal repository per tutte le migrazioni del codelab di App Engine che puoi clonare o scaricare un file ZIP.

Codelab

Python 2

Python 3

Module 1

codice

(n/d)

Modulo 2

codice

codice

Risorse App Engine

Di seguito sono riportate ulteriori risorse relative a questa specifica migrazione: