1. Panoramica
La serie di codelab Serverless Migration Station (tutorial pratici autogestiti) e i video correlati mirano ad aiutare gli sviluppatori di Google Cloud serverless a modernizzare le loro applicazioni guidandoli attraverso una o più migrazioni, principalmente l'abbandono dei servizi legacy. In questo modo, le tue app sono più portabili e hai più opzioni e flessibilità, il che ti consente di integrarle e accedere a una gamma più ampia di prodotti Cloud ed eseguire più facilmente l'upgrade alle versioni più recenti dei linguaggi. Sebbene inizialmente si concentri sui primi utenti di Cloud, principalmente gli sviluppatori di App Engine (ambiente standard), questa serie è abbastanza ampia da includere altre piattaforme serverless come Cloud Functions e Cloud Run o altre, se applicabile.
Questo codelab ti insegna come eseguire la migrazione dall'archivio BLOB di App Engine a Cloud Storage. Esistono anche migrazioni implicite da:
- Framework web
webapp2a Flask (trattato nel Modulo 1) - App Engine NDB a Cloud NDB per l'accesso a Datastore (trattato nel Modulo 2)
- Python 2 a 3 (l'app di cui è stata eseguita la migrazione è compatibile sia con Python 2 che con Python 3)
Per ulteriori informazioni dettagliate, consulta i moduli di migrazione correlati.
Imparerai a utilizzare
- Aggiungi l'utilizzo dell'API/libreria Blobstore di App Engine
- Archivia i caricamenti degli utenti nel servizio Blobstore
- Preparati al passaggio successivo per eseguire la migrazione a Cloud Storage
Che cosa ti serve
- Un progetto Google Cloud con un account di fatturazione Google Cloud attivo
- Competenze di base di Python
- Conoscenza pratica dei comandi Linux più comuni
- Conoscenza di base dello sviluppo e del deployment di app App Engine
- Un'app App Engine del Modulo 15 funzionante: completa il codelab del Modulo 15 (consigliato) o copia l'app del Modulo 15 dal repository
Sondaggio
Come utilizzerai questo tutorial?
Come valuteresti la tua esperienza con Python?
Come valuteresti la tua esperienza con l'utilizzo dei servizi Google Cloud?
2. Sfondo
Questo codelab inizia con l'app di esempio del Modulo 15 e mostra come eseguire la migrazione da Blobstore (e NDB) a Cloud Storage (e Cloud NDB). Il processo di migrazione prevede la sostituzione delle dipendenze dai servizi in bundle legacy di App Engine, che ti consentono di spostare le tue app su un'altra piattaforma serverless Cloud o su un'altra piattaforma di hosting, se lo desideri.
Questa migrazione richiede un po' più di impegno rispetto alle altre migrazioni di questa serie. Blobstore ha dipendenze dal webapp framework originale, motivo per cui l'app di esempio utilizza il framework webapp2 anziché Flask. Questo tutorial illustra le migrazioni a Cloud Storage, Cloud NDB, Flask e Python 3.
L'app registra ancora le "visite" degli utenti finali e visualizza le dieci più recenti, ma il codelab precedente (Modulo 15) ha aggiunto una nuova funzionalità per l'utilizzo di Blobstore: l'app chiede agli utenti finali di caricare un artefatto (un file) corrispondente alla loro "visita". Gli utenti possono farlo o selezionare "Salta" per disattivare l'opzione. Indipendentemente dalla decisione dell'utente, la pagina successiva mostra lo stesso output delle versioni precedenti di questa app, visualizzando le visite più recenti. Un'ulteriore particolarità è che le visite con artefatti corrispondenti presentano un link "Visualizza" per visualizzare l'artefatto di una visita. Questo codelab implementa le migrazioni menzionate in precedenza, preservando al contempo la funzionalità descritta.
3. Configurazione/preparazione
Prima di passare alla parte principale del tutorial, configuriamo il progetto, recuperiamo il codice ed eseguiamo il deployment dell'app di base per assicurarci di iniziare con un codice funzionante.
1. Configura il progetto
Se hai già eseguito il deployment dell'app del Modulo 15, 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. Scarica l'app di esempio di base
Uno dei prerequisiti di questo codelab è avere un'app di esempio del Modulo 15 funzionante. Se non ce l'hai, puoi scaricarla dalla cartella "START" del Modulo 15 (link di seguito). Questo codelab ti guida attraverso ogni passaggio, per concludere con un codice simile a quello presente nella cartella "FINISH" del Modulo 16.
- START: cartella Modulo 15 (Python 2)
- FINE: cartella del modulo 16 (Python 2)
- Intero repository (per clonare o scaricare il file ZIP)
La directory dei file START del Modulo 15 dovrebbe avere il seguente aspetto:
$ ls README.md app.yaml main-gcs.py main.py templates
Il file main-gcs.py è una versione alternativa di main.py del Modulo 15 che consente di selezionare un bucket Cloud Storage diverso dall'URL predefinito assegnato a un'app in base all'ID del progetto: PROJECT_ID.appspot.com. Questo file non ha alcun ruolo in questo codelab (Modulo 16), se non che è possibile applicare tecniche di migrazione simili a questo file, se lo si desidera.
3. (Riesegui il) deployment dell'app di base
I passaggi rimanenti della preparazione da eseguire ora:
- Acquisisci nuovamente familiarità con lo strumento a riga di comando
gcloud - Esegui di nuovo il deployment dell'app di esempio con
gcloud app deploy - Verifica che l'app venga eseguita su App Engine senza problemi
Dopo aver eseguito correttamente questi passaggi e aver confermato che l'app del Modulo 15 funziona, La pagina iniziale accoglie gli utenti con un modulo che richiede di caricare un file di artefatto della visita, insieme a un'opzione, un pulsante "Salta", per disattivare la funzionalità:

Una volta che gli utenti caricano un file o saltano il passaggio, l'app mostra la pagina familiare "Visite più recenti":

Le visite che includono un artefatto avranno un link "Visualizza" a destra del timestamp della visita per visualizzare (o scaricare) l'artefatto. Una volta confermata la funzionalità dell'app, potrai eseguire la migrazione dai servizi legacy di App Engine (webapp2, NDB, Blobstore) alle alternative moderne (Flask, Cloud NDB, Cloud Storage).
4. Aggiorna i file di configurazione
Per la versione aggiornata della nostra app entrano in gioco tre file di configurazione. Le attività richieste sono:
- Aggiornare le librerie di terze parti integrate richieste in
app.yamle lasciare aperta la porta a una migrazione a Python 3 - Aggiungi un
requirements.txtche specifichi tutte le librerie richieste che non sono integrate - Aggiungi
appengine_config.pyin modo che l'app supporti sia le librerie di terze parti integrate sia quelle non integrate
app.yaml
Modifica il file app.yaml aggiornando la sezione libraries. Rimuovi jinja2 e aggiungi grpcio, setuptools e ssl. Scegli l'ultima versione disponibile per tutte e tre le librerie. Aggiungi anche l'istruzione Python 3 runtime, ma commentata. Al termine, dovrebbe avere l'aspetto seguente (se hai selezionato Python 3.9):
PRIMA:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: jinja2
version: latest
AFTER:
#runtime: python39
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: grpcio
version: latest
- name: setuptools
version: latest
- name: ssl
version: latest
Le modifiche riguardano principalmente le librerie integrate di Python 2 disponibili sui server App Engine (in modo da non doverle raggruppare autonomamente). Abbiamo rimosso Jinja2 perché è incluso in Flask, che aggiungeremo a reqs.txt. Ogni volta che vengono utilizzate le librerie client di Google Cloud, come quelle per Cloud NDB e Cloud Storage, sono necessari grpcio e setuptools. Infine, Cloud Storage stesso richiede la libreria ssl. La direttiva di runtime commentata in alto serve per quando è tutto pronto per eseguire il porting di questa app in Python 3. Tratteremo questo argomento alla fine di questo tutorial.
requirements.txt
Aggiungi un file requirements.txt che richiede il framework Flask e le librerie client di Cloud NDB e Cloud Storage, nessuna delle quali è integrata. Crea il file con questi contenuti:
flask
google-cloud-ndb
google-cloud-storage
Il runtime Python 2 di App Engine richiede l'auto-bundling di librerie di terze parti non integrate, quindi esegui il comando seguente per installare queste librerie nella cartella lib:
pip install -t lib -r requirements.txt
Se sulla tua macchina di sviluppo sono presenti sia Python 2 che Python 3, potresti dover utilizzare il comando pip2 per assicurarti di ottenere le versioni Python 2 di queste librerie. Una volta eseguito l'upgrade a Python 3, non è più necessario eseguire il self-bundling.
appengine_config.py
Aggiungi un file appengine_config.py che supporti librerie di terze parti integrate e non integrate. Crea il file con questi contenuti:
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)
I passaggi appena completati dovrebbero essere simili o identici a quelli elencati nella sezione Installazione di librerie per app Python 2 della documentazione di App Engine e, più in particolare, i contenuti di appengine_config.py dovrebbero corrispondere a quelli del passaggio 5.
Il lavoro sui file di configurazione è completato, quindi passiamo all'applicazione.
5. Modifica i file dell'applicazione
Importazioni
Il primo set di modifiche per main.py include la sostituzione di tutti gli elementi da sostituire. Ecco cosa cambierà:
webapp2viene sostituito da Flask- Anziché utilizzare Jinja2 da
webapp2_extras, utilizza Jinja2 fornito con Flask - Blobstore e NDB di App Engine vengono sostituiti da Cloud NDB e Cloud Storage
- I gestori di Blobstore in
webappvengono sostituiti da una combinazione del modulo della libreria standardio, Flask e delle utilitàwerkzeug - Per impostazione predefinita, Blobstore scrive in un bucket Cloud Storage denominato in base all'URL dell'app (
PROJECT_ID.appspot.com). Poiché stiamo eseguendo il porting alla libreria client di Cloud Storage,google.authviene utilizzato per ottenere l'ID progetto per specificare esattamente lo stesso nome del bucket. (Puoi modificare il nome del bucket poiché non è più impostato come hardcoded).
PRIMA:
import webapp2
from webapp2_extras import jinja2
from google.appengine.ext import blobstore, ndb
from google.appengine.ext.webapp import blobstore_handlers
Implementa le modifiche nell'elenco riportato sopra sostituendo l'attuale sezione di importazione in main.py con lo snippet di codice riportato di seguito.
AFTER:
import io
from flask import (Flask, abort, redirect, render_template,
request, send_file, url_for)
from werkzeug.utils import secure_filename
import google.auth
from google.cloud import exceptions, ndb, storage
Inizializzazione e supporto Jinja2 non necessario
Il blocco di codice successivo da sostituire è BaseHandler, che specifica l'utilizzo di Jinja2 da webapp2_extras. Questo non è necessario perché Jinja2 è incluso in Flask ed è il suo motore di template predefinito, quindi rimuovilo.
Sul lato del Modulo 16, crea un'istanza degli oggetti che non avevamo nell'app precedente. Ciò include l'inizializzazione dell'app Flask e la creazione di client API per Cloud NDB e Cloud Storage. Infine, creiamo il nome del bucket Cloud Storage come descritto sopra nella sezione delle importazioni. Ecco i risultati prima e dopo l'implementazione di questi aggiornamenti:
PRIMA:
class BaseHandler(webapp2.RequestHandler):
'Derived request handler mixing-in Jinja2 support'
@webapp2.cached_property
def jinja2(self):
return jinja2.get_jinja2(app=self.app)
def render_response(self, _template, **context):
self.response.write(self.jinja2.render_template(_template, **context))
AFTER:
app = Flask(__name__)
ds_client = ndb.Client()
gcs_client = storage.Client()
_, PROJECT_ID = google.auth.default()
BUCKET = '%s.appspot.com' % PROJECT_ID
Aggiorna l'accesso a Datastore
Cloud NDB è per lo più compatibile con App Engine NDB. Una differenza già trattata è la necessità di un client API. Un'altra è che quest'ultimo richiede che l'accesso a Datastore sia controllato dal gestore del contesto Python del client API. In sostanza, ciò significa che tutte le chiamate di accesso a Datastore che utilizzano la libreria client Cloud NDB possono essere eseguite solo all'interno di blocchi Python with.
Questa è una modifica; l'altra è che Blobstore e i suoi oggetti, ad esempio BlobKey, non sono supportati da Cloud Storage, quindi modifica file_blob in modo che sia ndb.StringProperty. Di seguito sono riportate la classe del modello di dati e le funzioni store_visit() e fetch_visits() aggiornate che riflettono queste modifiche:
PRIMA:
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
file_blob = ndb.BlobKeyProperty()
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_blob=upload_key).put()
def fetch_visits(limit):
'get most recent visits'
return Visit.query().order(-Visit.timestamp).fetch(limit)
AFTER:
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
file_blob = ndb.StringProperty()
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_blob=upload_key).put()
def fetch_visits(limit):
'get most recent visits'
with ds_client.context():
return Visit.query().order(-Visit.timestamp).fetch(limit)
Ecco una rappresentazione grafica delle modifiche apportate finora:

Aggiornamento dei gestori
Gestore di caricamento
I gestori in webapp2 sono classi, mentre in Flask sono funzioni. Anziché un metodo con verbo HTTP, Flask utilizza il verbo per decorare la funzione. Blobstore e i relativi gestori webapp vengono sostituiti dalle funzionalità di Cloud Storage, nonché da Flask e dalle relative utilità:
PRIMA:
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
'Upload blob (POST) handler'
def post(self):
uploads = self.get_uploads()
blob_id = uploads[0].key() if uploads else None
store_visit(self.request.remote_addr, self.request.user_agent, blob_id)
self.redirect('/', code=307)
AFTER:
@app.route('/upload', methods=['POST'])
def upload():
'Upload blob (POST) handler'
fname = None
upload = request.files.get('file', None)
if upload:
fname = secure_filename(upload.filename)
blob = gcs_client.bucket(BUCKET).blob(fname)
blob.upload_from_file(upload, content_type=upload.content_type)
store_visit(request.remote_addr, request.user_agent, fname)
return redirect(url_for('root'), code=307)
Alcune note su questo aggiornamento:
- Anziché un
blob_id, gli artefatti dei file sono ora identificati dal nome file (fname), se presente, e daNonein caso contrario (l'utente ha disattivato il caricamento di un file). - I gestori di Blobstore hanno astratto il processo di caricamento dai suoi utenti, ma Cloud Storage non lo fa, quindi puoi vedere il codice appena aggiunto che imposta l'oggetto blob e la posizione (bucket) del file, nonché la chiamata che esegue il caricamento effettivo. (
upload_from_file()). webapp2utilizza una tabella di routing nella parte inferiore del file dell'applicazione, mentre le route di Flask si trovano in ogni gestore decorato.- Entrambi i gestori concludono la loro funzionalità reindirizzando alla home page (
/) e conservando la richiestaPOSTcon un codice di ritorno HTTP 307.
Gestore dei download
L'aggiornamento del gestore dei download segue un pattern simile a quello del gestore dei caricamenti, ma con molto meno codice da esaminare. Sostituisci la funzionalità Blobstore e webapp con gli equivalenti di Cloud Storage e Flask:
PRIMA:
class ViewBlobHandler(blobstore_handlers.BlobstoreDownloadHandler):
'view uploaded blob (GET) handler'
def get(self, blob_key):
self.send_blob(blob_key) if blobstore.get(blob_key) else self.error(404)
AFTER:
@app.route('/view/<path:fname>')
def view(fname):
'view uploaded blob (GET) handler'
blob = gcs_client.bucket(BUCKET).blob(fname)
try:
media = blob.download_as_bytes()
except exceptions.NotFound:
abort(404)
return send_file(io.BytesIO(media), mimetype=blob.content_type)
Note su questo aggiornamento:
- Anche in questo caso, Flask decora le funzioni di gestione con la loro route, mentre
webapplo fa in una tabella di routing in basso, quindi riconosci la sintassi di corrispondenza dei pattern di quest'ultimo (('/view/([^/]+)?') rispetto a quella di Flask ('/view/<path:fname>'). - Come per il gestore dei caricamenti, sul lato Cloud Storage è necessario un po' di lavoro in più per le funzionalità astratte dai gestori Blobstore, ovvero l'identificazione del file (blob) in questione e il download esplicito del file binario rispetto alla singola chiamata al metodo
send_blob()del gestore Blobstore. - In entrambi i casi, se un artefatto non viene trovato, all'utente viene restituito un errore HTTP 404.
Gestore principale
Le modifiche finali all'applicazione principale vengono apportate nel gestore principale. I metodi dei verbi HTTP webapp2 vengono sostituiti da una singola funzione che ne combina le funzionalità. Sostituisci la classe MainHandler con la funzione root() e rimuovi la tabella di routing webapp2 come mostrato di seguito:
PRIMA:
class MainHandler(BaseHandler):
'main application (GET/POST) handler'
def get(self):
self.render_response('index.html',
upload_url=blobstore.create_upload_url('/upload'))
def post(self):
visits = fetch_visits(10)
self.render_response('index.html', visits=visits)
app = webapp2.WSGIApplication([
('/', MainHandler),
('/upload', UploadHandler),
('/view/([^/]+)?', ViewBlobHandler),
], debug=True)
AFTER:
@app.route('/', methods=['GET', 'POST'])
def root():
'main application (GET/POST) handler'
context = {}
if request.method == 'GET':
context['upload_url'] = url_for('upload')
else:
context['visits'] = fetch_visits(10)
return render_template('index.html', **context)
Anziché metodi get() e post() separati, sono essenzialmente un'istruzione if-else in root(). Inoltre, poiché root() è una singola funzione, esiste una sola chiamata per eseguire il rendering del template sia per GET che per POST, mentre non è possibile in webapp2.
Ecco una rappresentazione grafica di questa seconda e ultima serie di modifiche a main.py:

(Facoltativo) "Miglioramento" della compatibilità con le versioni precedenti
La soluzione creata sopra funziona perfettamente, ma solo se inizi da zero e non hai file creati da Blobstore. Poiché abbiamo aggiornato l'app per identificare i file in base al nome file anziché a BlobKey, l'app del Modulo 16 completata così com'è non sarà in grado di visualizzare i file di Blobstore. In altre parole, abbiamo apportato una modifica incompatibile con le versioni precedenti eseguendo questa migrazione. Ora presentiamo una versione alternativa di main.py chiamata main-migrate.py (disponibile nel repository) che tenta di colmare questa lacuna.
La prima "estensione" per supportare i file creati da Blobstore è un modello di dati che ha un BlobKeyProperty (oltre a un StringProperty per i file creati da Cloud Storage):
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
file_blob = ndb.BlobKeyProperty() # backwards-compatibility
file_gcs = ndb.StringProperty()
La proprietà file_blob verrà utilizzata per identificare i file creati da Blobstore, mentre file_gcs è per i file di Cloud Storage. Ora, quando crei nuove visite, memorizza esplicitamente un valore in file_gcs anziché in file_blob, in modo che store_visit abbia un aspetto leggermente diverso:
PRIMA:
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_blob=upload_key).put()
AFTER:
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_gcs=upload_key).put()
Quando recuperi le visite più recenti, "normalizza" i dati prima di inviarli al modello:
PRIMA:
@app.route('/', methods=['GET', 'POST'])
def root():
'main application (GET/POST) handler'
context = {}
if request.method == 'GET':
context['upload_url'] = url_for('upload')
else:
context['visits'] = fetch_visits(10)
return render_template('index.html', **context)
AFTER:
@app.route('/', methods=['GET', 'POST'])
def root():
'main application (GET/POST) handler'
context = {}
if request.method == 'GET':
context['upload_url'] = url_for('upload')
else:
context['visits'] = etl_visits(fetch_visits(10))
return render_template('index.html', **context)
Poi, conferma l'esistenza di file_blob o file_gcs (o di nessuno dei due). Se è disponibile un file, scegli quello esistente e utilizza l'identificatore (BlobKey per i file creati da Blobstore o il nome file per i file creati da Cloud Storage). Quando diciamo "file creati da Cloud Storage", intendiamo i file creati utilizzando la libreria client di Cloud Storage. Anche Blobstore scrive in Cloud Storage, ma in questo caso si tratta di file creati da Blobstore.
Ora, cosa più importante, cos'è questa funzione etl_visits() utilizzata per normalizzare o eseguire l'ETL (estrazione, trasformazione e caricamento) dei dati per l'utente finale? Ha questo aspetto:
def etl_visits(visits):
return [{
'visitor': v.visitor,
'timestamp': v.timestamp,
'file_blob': v.file_gcs if hasattr(v, 'file_gcs') \
and v.file_gcs else v.file_blob
} for v in visits]
Probabilmente è come ti aspettavi: il codice esegue un loop di tutte le visite e, per ogni visita, prende i dati del visitatore e del timestamp alla lettera, poi controlla se esiste file_gcs o file_blob e, se sì, ne sceglie uno (o None se non esiste nessuno dei due).
Ecco un'illustrazione delle differenze tra main.py e main-migrate.py:

Se inizi da zero senza file creati da Blobstore, utilizza main.py, ma se stai eseguendo la transizione e vuoi supportare i file creati sia da Blobstore sia da Cloud Storage, dai un'occhiata a main-migrate.py come esempio di come gestire uno scenario simile per aiutarti a pianificare le migrazioni per le tue app. Quando si eseguono migrazioni complesse, è probabile che si verifichino casi speciali, quindi questo esempio ha lo scopo di mostrare una maggiore affinità con la modernizzazione di app reali con dati reali.
6. Riepilogo/pulizia
Questa sezione conclude questo codelab con il deployment dell'app, la verifica del suo funzionamento come previsto e l'analisi dell'output generato. Dopo la convalida dell'app, esegui i passaggi di pulizia e valuta i passaggi successivi.
Esegui il deployment e verifica l'applicazione
Prima di rifare il deployment dell'app, assicurati di eseguire pip install -t lib -r requirements.txt per inserire le librerie di terze parti raggruppate autonomamente nella cartella lib. Se vuoi eseguire la soluzione compatibile con le versioni precedenti, rinomina prima main-migrate.py in main.py. Ora esegui gcloud app deploy e verifica che l'app funzioni in modo identico all'app del Modulo 15. La schermata del modulo ha il seguente aspetto:

La pagina delle visite più recenti ha questo aspetto:

Complimenti per aver completato questo codelab che sostituisce Blobstore di App Engine con Cloud Storage, NDB di App Engine con Cloud NDB e webapp2 con Flask. Il codice ora dovrebbe corrispondere a quello nella cartella FINISH (Module 16). Anche l'alternativa main-migrate.py è presente in quella cartella.
"Migrazione" a Python 3
La direttiva Python 3 runtime commentata nella parte superiore di app.yaml è tutto ciò che serve per eseguire il porting di questa app su Python 3. Il codice sorgente è già compatibile con Python 3, quindi non sono necessarie modifiche. Per eseguire il deployment come app Python 3, segui questi passaggi:
- Rimuovi il commento dalla direttiva Python 3
runtimenella parte superiore diapp.yaml. - Elimina tutte le altre righe in
app.yaml. - Elimina il file
appengine_config.py. (non utilizzato nel runtime Python 3) - Elimina la cartella
lib, se esiste. (non necessario con il runtime Python 3)
Esegui la pulizia
Generale
Se hai finito, ti consigliamo di disattivare l'app App Engine per evitare addebiti. Tuttavia, se vuoi eseguire altri test o esperimenti, la piattaforma App Engine ha una quota senza costi, quindi, se non superi questo livello di utilizzo, non ti verranno addebitati costi. Questo vale per il computing, ma potrebbero essere addebitati anche i costi per i servizi App Engine pertinenti, quindi consulta la pagina dei prezzi per ulteriori informazioni. Se questa migrazione coinvolge altri servizi Cloud, questi vengono fatturati separatamente. In entrambi i casi, se applicabile, consulta la sezione "Specifico per questo codelab" di seguito.
Per completezza, il deployment su una piattaforma di serverless computing di Google Cloud come App Engine comporta costi minimi di build e archiviazione. Cloud Build ha una propria quota senza costi, così come Cloud Storage. L'archiviazione di questa immagine utilizza parte di questa quota. Tuttavia, potresti vivere in una regione che non dispone di un livello senza costi, quindi tieni d'occhio l'utilizzo dello spazio di archiviazione per ridurre al minimo i potenziali costi. Le "cartelle" di Cloud Storage specifiche che devi esaminare includono:
console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/imagesconsole.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com- I link allo spazio di archiviazione riportati sopra dipendono dal tuo
PROJECT_IDe 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, chiudi il progetto.
Specifico per questo codelab
I servizi elencati di seguito sono univoci per questo codelab. Per saperne di più, consulta la documentazione di ciascun prodotto:
- Il servizio Blobstore di App Engine rientra nelle quote e nei limiti dei dati archiviati, quindi consulta anche la pagina dei prezzi per i servizi in bundle legacy.
- Cloud Storage offre un livello senza costi per regioni specifiche. Per ulteriori informazioni, consulta anche la pagina dei prezzi generali.
- Il servizio App Engine Datastore è fornito da Cloud Datastore (Cloud Firestore in modalità Datastore), che offre anche un Livello senza costi; per ulteriori informazioni, consulta la pagina dei prezzi.
Tieni presente che se hai eseguito la migrazione dal Modulo 15 al 16, avrai ancora dati in Blobstore, motivo per cui includiamo le informazioni sui prezzi riportate sopra.
Passaggi successivi
Oltre a questo tutorial, altri moduli di migrazione incentrati sull'abbandono dei servizi in bundle legacy da considerare includono:
- Modulo 2: esegui la migrazione da App Engine
ndba Cloud NDB - Moduli 7-9: esegui la migrazione dalle attività push della coda di attività di App Engine a Cloud Tasks
- Moduli 12-13: esegui la migrazione da App Engine Memcache a Cloud Memorystore
- Moduli 18-19: esegui la migrazione dalla coda di attività di App Engine (attività pull) a Cloud Pub/Sub
App Engine non è più l'unica piattaforma serverless di Google Cloud. Se hai un'app App Engine di piccole dimensioni o con funzionalità limitate e vuoi trasformarla in un microservizio autonomo oppure se vuoi suddividere un'app monolitica in più componenti riutilizzabili, questi sono buoni motivi per prendere in considerazione il passaggio a Cloud Functions. Se la containerizzazione è diventata parte del flusso di lavoro di sviluppo delle applicazioni, in particolare se consiste in una pipeline CI/CD (integrazione continua/distribuzione continua o deployment continuo), valuta la possibilità di eseguire la migrazione a Cloud Run. Questi scenari sono trattati nei seguenti moduli:
- Esegui 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 o il Modulo 5 per farlo senza container, conoscenze di Docker o
Dockerfile
Il passaggio a un'altra piattaforma serverless è facoltativo e ti consigliamo di valutare le opzioni migliori per le tue app e i tuoi casi d'uso prima di apportare qualsiasi modifica.
Indipendentemente dal modulo di migrazione che prenderai in considerazione, tutti i contenuti della Serverless Migration Station (codelab, video, codice sorgente [se disponibile]) sono accessibili nel relativo repository open source. Il file README del repository fornisce anche indicazioni su quali migrazioni considerare e sull'eventuale "ordine" pertinente dei moduli di migrazione.
7. Risorse aggiuntive
Problemi/feedback relativi ai codelab
Se riscontri problemi con questo codelab, cerca il problema prima di segnalarlo. Link per cercare e creare nuovi problemi:
Risorse per la migrazione
I link alle cartelle del repository per il Modulo 15 (START) e il Modulo 16 (FINISH) sono disponibili nella tabella seguente. Puoi accedervi anche dal repository per tutte le migrazioni dei codelab di App Engine, che puoi clonare o scaricare come file ZIP.
Codelab | Python 2 | Python 3 |
Modulo 15 | N/A | |
Modulo 16 (questo codelab) | (come per Python 2) |
Risorse online
Di seguito sono riportate le risorse online che potrebbero essere pertinenti per questo tutorial:
Blobstore di App Engine e Cloud Storage
- Servizio Blobstore di App Engine
- Migrazione alla libreria client di Cloud Storage
- Home page di Cloud Storage
- Documentazione di Cloud Storage
Piattaforma App Engine
- Documentazione di App Engine
- Runtime di Python 2 App Engine (ambiente standard)
- Utilizzo delle librerie integrate di App Engine su Python 2 App Engine
- Runtime Python 3 di App Engine (ambiente standard)
- Differenze tra i runtime di App Engine (ambiente standard) Python 2 e 3
- Guida alla migrazione di App Engine (ambiente standard) da Python 2 a 3
- Informazioni su prezzi e quote di App Engine
- Lancio della piattaforma App Engine di seconda generazione (2018)
- Confronto tra piattaforme di prima e seconda generazione
- Assistenza a lungo termine per i runtime legacy
- Repository di esempi di migrazione della documentazione
- Repository di esempi di migrazione forniti dalla community
Altre informazioni sul cloud
- Python su Google Cloud Platform
- Librerie client Python di Google Cloud
- Livello "Always Free" di Google Cloud
- Google Cloud SDK (strumento a riga di comando
gcloud) - Tutta la documentazione di Google Cloud
Python
- Sistemi di modelli Django e Jinja2
- Framework web
webapp2 - Documentazione di
webapp2 webapp2_extraslink- Documentazione di Jinja2
webapp2_extras - Framework web Flask
Video
- Serverless Migration Station
- Serverless Expeditions
- 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.