1. Panoramica
Questa serie di codelab (tutorial pratici e autogestiti) ha lo scopo di aiutare gli sviluppatori di Google App Engine (standard) a modernizzare le loro app guidandoli attraverso una serie di migrazioni. La maggior parte di queste migrazioni prevede l'abbandono dei servizi di runtime originali in bundle perché i runtime di nuova generazione sono più flessibili e offrono agli utenti una maggiore varietà di opzioni di servizio. Un altro modo per modernizzare un'app è eseguire l'upgrade a un prodotto più recente, ed è questo l'argomento di questo codelab.
Gli utenti di App Engine che accedono a Datastore con le librerie client Cloud NDB o Cloud Datastore sono pronti e non devono eseguire ulteriori migrazioni. Tuttavia, Cloud Firestore rappresenta l'archivio dati NoSQL più recente, scalabile e a disponibilità elevata, con funzionalità del database Firebase in tempo reale.
Ti trovi nel posto giusto se sei uno sviluppatore che si sente in dovere di utilizzare Firestore per sfruttare le sue funzionalità o che ha almeno abbastanza interesse per capire cosa comporta la migrazione. Questo tutorial mostra come eseguire la migrazione di un'app App Engine che utilizza Cloud Datastore a Cloud Firestore.
Imparerai come
- Riconoscere le differenze tra Datastore e Firestore
- Esegui la migrazione da Cloud Datastore a Cloud Firestore
Che cosa ti serve
- Un progetto Google Cloud con:
- Competenze di base di Python
- Conoscenza pratica dei comandi Linux più comuni
- Conoscenza di base dello sviluppo e del deployment di app App Engine
- Ti consigliamo di completare il codelab del modulo 3, incluso il porting a Python 3, prima di iniziare questo (modulo 6).
- Un'app Python 3 App Engine Cloud Datastore del modulo 3 funzionante.
Sondaggio
Come utilizzerai questo codelab?
2. Sfondo
Datastore di App Engine è diventato un prodotto autonomo nel 2013, Google Cloud Datastore, ed è ora accessibile agli sviluppatori al di fuori di App Engine. L'anno successivo, Firebase è stata acquisita da Google. All'epoca, era noto per il suo database in tempo reale.
Nei successivi anni, i team di Firebase e Cloud Datastore hanno lavorato all'integrazione di alcune funzionalità di Firebase in Datastore. Di conseguenza, nel 2017 è stata rilasciata la nuova generazione di Cloud Datastore. Per riflettere l'ereditarietà di alcune funzionalità di Firebase, è stato rinominato Cloud Firestore.
Cloud Firestore è diventato il meccanismo di archiviazione NoSQL predefinito per i progetti Google Cloud. Le nuove app possono utilizzare Cloud Firestore in modo nativo, mentre i database Datastore esistenti sono stati convertiti in Firestore in modo trasparente e ora funzionano come "Firestore in modalità Datastore" per preservare la compatibilità con le operazioni Datastore. Di conseguenza, le applicazioni possono utilizzare Cloud Firestore solo in una di queste modalità e, una volta impostata, non può essere modificata.
Attualmente, quando gli utenti creano nuovi progetti e selezionano una soluzione NoSQL, viene chiesto loro di scegliere tra Firestore in modalità Datastore o Firestore in modalità nativa. Una volta aggiunte le entità Datastore, gli utenti non possono passare a Firestore e, allo stesso modo, una volta selezionata la modalità nativa di Firestore, non possono più tornare a Datastore (o meglio, a Firestore in modalità Datastore). Per ulteriori dettagli, leggi la pagina Scelta tra Cloud Firestore in modalità Datastore o modalità Firestore nativa nella documentazione. Per eseguire la migrazione di un'app a Firestore, è necessario creare un nuovo progetto, esportare Datastore e importarlo in Firestore. Lo scopo di questo tutorial è fornire agli sviluppatori un'idea delle differenze tra l'utilizzo di Cloud Datastore e Cloud Firestore.
Questa migrazione non è una di quelle che ci aspettiamo che gli utenti eseguano, motivo per cui è facoltativa. Sebbene l'utilizzo nativo di Cloud Firestore offra vantaggi evidenti, come l'autenticazione client, l'integrazione delle regole Firebase e, naturalmente, il database in tempo reale Firebase, i passaggi di migrazione sono "scomodi":
- Devi utilizzare un progetto diverso da quello della tua app attuale.
- Un progetto in cui un'app ha aggiunto entità Datastore non può passare a Firestore in modalità nativa
- Allo stesso modo, un progetto che ha selezionato Firestore in modalità nativa non può tornare a Firestore in modalità Datastore.
- Non esiste uno strumento di migrazione in grado di trasmettere dati in streaming da un progetto a un altro.
- Alcune funzionalità fondamentali di Datastore, tra cui gli spazi dei nomi e una velocità effettiva di scrittura più elevata (> 10.000/s), non sono disponibili da Firestore.
- Gli strumenti di esportazione e importazione sono scenari "primitivi" e "tutto o niente".
- Se la tua app ha molte entità Datastore, l'esportazione e l'importazione in Firestore possono richiedere molte ore.
- Durante questo periodo, la tua applicazione/il tuo servizio non potrà scrivere/aggiornare i dati.
- Le attività di migrazione vengono conteggiate nell'utilizzo normale; ti consigliamo di distribuirle (tra le quote giornaliere, se possibile) per ridurre al minimo i costi.
- Poiché il nuovo servizio viene eseguito in un progetto diverso, è necessario un periodo di tempo per la propagazione degli aggiornamenti DNS.
- Datastore e Firestore hanno modelli di dati simili ma diversi, quindi la migrazione richiede l'aggiornamento del funzionamento dell'app/servizio
- Le query sugli antenati di Datastore ora sono query sulle raccolte di Firestore (impostazione predefinita)
- Le query di tipo ampio di Datastore sono query di gruppo di raccolte Firestore
- Gli indici e la gestione sono diversi e così via.
Detto questo, se hai un'app abbastanza semplice da prendere in considerazione per la migrazione, se ti stai preparando a simulare una migrazione o se sei qui semplicemente per saperne di più su Datastore e Firestore, continua a leggere.
Utenti di Python 2:questo codelab di migrazione facoltativo è presentato solo in Python 3, ma poiché Cloud Firestore supporta anche la versione 2.x, gli utenti possono interpolare le differenze di utilizzo. Un esempio è che i record Firestore utilizzano stringhe Unicode (anziché stringhe di byte), quindi è necessario un indicatore iniziale u'' per i valori letterali stringa di Python 2, il che significa che una funzione store_visit() 2.x avrà il seguente aspetto:
def store_visit(remote_addr, user_agent):
doc_ref = fs_client.collection(u'Visit')
doc_ref.add({
u'timestamp': datetime.now(),
u'visitor': u'{}: {}'.format(remote_addr, user_agent),
})
A parte questo, la libreria client dovrebbe funzionare in modo simile. L'unico altro problema da prendere in considerazione è che la libreria Cloud Firestore 2.x è "congelata" per quanto riguarda lo sviluppo, quindi sempre più funzionalità nuove/più recenti saranno disponibili solo nella libreria client Firestore 3.x.
Se procedi con questa migrazione, i passaggi principali di questo tutorial sono:
- Configurazione/preparazione
- Aggiungi la libreria Cloud Firestore
- Aggiorna i file dell'applicazione
3. Configurazione/preparazione
Prima di iniziare la parte principale del tutorial, configuriamo il progetto, recuperiamo il codice e poi implementiamo l'app di base per assicurarci di iniziare con un codice funzionante.
1. Configura il progetto
Ti consigliamo di riutilizzare lo stesso progetto che hai utilizzato per completare il codelab del modulo 3. In alternativa, puoi creare un nuovo progetto o riutilizzarne uno esistente. Assicurati che il progetto abbia un account di fatturazione attivo e che App Engine (app) sia abilitato.
2. Ottieni l'app di esempio di base
Uno dei prerequisiti di questo codelab è avere un'app di esempio del modulo 3 funzionante. Se non ne hai una, completa il tutorial del modulo 3 (link sopra) prima di procedere. Altrimenti, se hai già familiarità con i contenuti, puoi iniziare prendendo il codice del modulo 3 di seguito.
Che tu utilizzi il tuo o il nostro, il codice del modulo 3 è il punto di partenza. Questo codelab del modulo 6 ti guida in ogni passaggio e, una volta completato, dovrebbe assomigliare al codice nel punto FINISH. Questo tutorial è disponibile solo per Python 3.
- INIZIO: Repository del Modulo 3
- FINISH: Module 6 repo
- Intero repository (clona o scarica ZIP)
La directory dei file del Modulo 3 (tuoi o nostri) dovrebbe avere il seguente aspetto:
$ ls
README.md main.py templates
app.yaml requirements.txt
3. (Esegui di nuovo il deployment dell'app del modulo 3
I passaggi preliminari rimanenti da eseguire ora:
- Acquisisci di nuovo familiarità con lo strumento a riga di comando
gcloud(se necessario). - (Esegui di nuovo il deployment del codice del modulo 3 in App Engine (se necessario))
Una volta eseguiti correttamente questi passaggi e verificato che sia operativo, andremo avanti in questo tutorial, a partire dai file di configurazione.
Requisiti di Python 2
- Assicurati che
app.yamlfaccia ancora riferimento ai pacchetti di terze parti inclusi:grpcioesetuptools. - Assicurati che
appengine_config.pyutilizzi ancorapkg_resourcesegoogle.appengine.ext.vendorper indirizzare l'app a risorse di terze parti. - Nella sezione successiva, Aggiornamento di
requirements.txt, devi utilizzaregoogle-cloud-firestore==1.9.0, in quanto si tratta della versione finale compatibile con la versione 2.x della libreria client Python Firestore.- Se il tuo
requirements.txtha una voce pergoogle-cloud-core, lasciala invariata. - Elimina
libe reinstalla conpip install -t lib -r requirements.txt.
- Se il tuo
4. Aggiorna i file di configurazione (aggiungi la libreria Cloud Firestore)
Oltre alla configurazione, i passaggi successivi necessari sono l'aggiornamento della configurazione seguito dai file dell'applicazione. Per il primo, l'unica modifica alla configurazione è una piccola sostituzione del pacchetto nel file requirements.txt, quindi procediamo subito.
Sostituisci la riga google-cloud-datastore con google-cloud-firestore in requirements.txt in modo che abbia il seguente aspetto:
Flask==1.1.2
google-cloud-firestore==2.0.2
Ti consigliamo di utilizzare le versioni più recenti di ogni libreria. I numeri di versione riportati sopra sono gli ultimi disponibili al momento della stesura di questo articolo. Il codice nella cartella del repository FINISH viene aggiornato più frequentemente e potrebbe avere una versione più recente.
Non sono state apportate altre modifiche alla configurazione, quindi app.yaml e templates/index.html rimangono invariati.
5. Aggiorna i file dell'applicazione
Esiste un solo file dell'applicazione, main.py, quindi tutte le modifiche apportate a questa sezione interessano solo questo file.
1. Importazioni
Il passaggio all'importazione del pacchetto è una modifica secondaria da datastore a firestore:
- PRIMA:
from google.cloud import datastore
- DOPO:
from google.cloud import firestore
2. Accesso a Firestore
Dopo aver inizializzato Flask, crea il client Firestore. Apporta una modifica simile a quella precedente, ma per l'inizializzazione del client:
- PRIMA:
app = Flask(__name__)
ds_client = datastore.Client()
- DOPO:
app = Flask(__name__)
fs_client = firestore.Client()
Eseguendo la migrazione da Cloud NDB a Cloud Datastore, hai già fatto il lavoro più difficile per passare a Cloud Firestore. Con Datastore, crei record di dati sotto forma di entità costituite da proprietà comuni e le raggruppi per chiavi. I record di dati in Firestore sono documenti, composti da coppie chiave-valore e raggruppati in raccolte. La migrazione da Datastore richiede di considerare queste differenze, perché si materializzeranno durante la creazione dei record di dati e durante l'esecuzione di query. I risultati possono variare a seconda della complessità del codice Datastore.
Per Datastore, esegui query basate sul tipo di entità insieme a criteri di filtro e ordinamento. Per Firestore, l'esecuzione di query sui dati è simile. Vediamo un breve esempio, supponendo questi valori di query, client (ds_client o fs_client, rispettivamente) e importazioni:
from datetime import datetime
from firestore.Query import DESCENDING
OCT1 = datetime(2020, 10, 1)
LIMIT = 10
Per Datastore, eseguiamo una query per le dieci entità Visit più recenti successive al 1° ottobre 2020 in ordine decrescente:
query = ds_client.query(kind='Visit')
query.add_filter('timestamp', '>=', datetime(2020, 10, 1))
query.order = ['-timestamp']
return query.fetch(limit=LIMIT)
Esegui la stessa operazione per Firestore, dalla raccolta Visit:
query = fs_client.collection('Visit')
query.where('timestamp', '>=', datetime(2020, 10, 1))
query.order_by('timestamp', direction=DESCENDING)
return query.limit(LIMIT).stream()
La query dell'app di esempio è più semplice (nessuna clausola "WHERE"). Come riepilogo, ecco il codice Cloud Datastore:
- PRIMA:
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)
Se esegui la migrazione a Firestore, la creazione di nuovi documenti sarà simile a quella delle entità e le query saranno quelle mostrate in precedenza.
- DOPO:
def store_visit(remote_addr, user_agent):
doc_ref = fs_client.collection('Visit')
doc_ref.add({
'timestamp': datetime.now(),
'visitor': '{}: {}'.format(remote_addr, user_agent),
})
def fetch_visits(limit):
visits_ref = fs_client.collection('Visit')
visits = (v.to_dict() for v in visits_ref.order_by('timestamp',
direction=firestore.Query.DESCENDING).limit(limit).stream())
return visits
La funzione principale root() rimane invariata, così come il file modello index.html. Controlla attentamente le modifiche, salvale, esegui il deployment e verifica.
6. Riepilogo/Pulizia
Esegui il deployment di un'applicazione
Esegui nuovamente il deployment dell'app con gcloud app deploy e verifica che funzioni. Il codice ora dovrebbe corrispondere a quello del repository del modulo 6 (o a una versione 2.x, se preferisci).
Se hai iniziato questa serie senza aver svolto i codelab precedenti, l'app non cambia. Registra tutte le visite alla pagina web principale (/) e ha questo aspetto dopo che hai visitato il sito un numero sufficiente di volte:

Congratulazioni per aver completato questa migrazione facoltativa del modulo 6. Questa è probabilmente una delle ultime migrazioni che puoi eseguire per quanto riguarda l'archiviazione dei dati di App Engine. Una migrazione alternativa che puoi prendere in considerazione è la containerizzazione dell'app per Cloud Run, se non l'hai già fatto (vedi i moduli 4 e 5 dei codelab collegati di seguito).
(Facoltativo) Pulizia
Eseguire la pulizia per evitare addebiti fino a quando non sarai pronto per passare al codelab di migrazione successivo. In qualità di sviluppatori esistenti, probabilmente siete già aggiornati sulle informazioni sui prezzi di App Engine.
(Facoltativo) Disattiva l'app
Se non sei ancora pronto per passare al tutorial successivo, disattiva l'app per evitare addebiti. Quando vuoi passare al codelab successivo, puoi riattivarlo. Mentre la tua app è disattivata, non riceverà traffico per generare addebiti. Tuttavia, un altro aspetto per cui potresti ricevere addebiti è l'utilizzo di Firestore se supera la quota senza costi, quindi elimina i dati sufficienti per rientrare in questo limite.
D'altra parte, se non intendi continuare con le migrazioni e vuoi eliminare tutto completamente, puoi chiudere il progetto.
Passaggi successivi
Oltre a questo tutorial, esistono diversi altri codelab sui moduli di migrazione che puoi prendere in considerazione:
- Modulo 7: code di attività push di App Engine (obbligatorio se utilizzi le code di attività [push])
- Aggiunge le attività push di App Engine
taskqueueall'app del modulo 1 - Prepara gli utenti alla migrazione a Cloud Tasks nel modulo 8
- Aggiunge le attività push di App Engine
- Modulo 4: esegui la migrazione a Cloud Run con Docker
- Containerizzare l'app per eseguirla su Cloud Run con Docker
- Questa migrazione ti consente di continuare a utilizzare Python 2.
- Modulo 5: esegui la migrazione a Cloud Run con Cloud Buildpacks
- Containerizzare l'app per eseguirla su Cloud Run con Cloud Buildpacks
- Non devi sapere nulla di Docker, dei container o di
Dockerfile. - Richiede che l'app sia già stata migrata a Python 3 (Buildpacks non supporta Python 2)
7. Risorse aggiuntive
Problemi/feedback relativi ai codelab del modulo di migrazione di App Engine
Se riscontri problemi con questo codelab, cerca prima il tuo problema prima di presentare una segnalazione. Link per cercare e creare nuovi problemi:
Risorse per la migrazione
I link alle cartelle del repository per il modulo 3 (INIZIO) e il modulo 6 (FINE) sono disponibili nella tabella riportata di seguito. Puoi accedervi anche dal repository per tutte le migrazioni di App Engine, che puoi clonare o scaricare come file ZIP.
Codelab | Python 2 | Python 3 |
(codice) | ||
Modulo 6 | (n/a) |
Risorse App Engine
Di seguito sono riportate risorse aggiuntive relative a questa migrazione specifica:
- Riferimenti a Python Cloud Datastore e Cloud Firestore
- Migrazione a Python 3 e al runtime di nuova generazione di GAE
- Generale