1. Panoramica
La serie di codelab Serverless Migration Station (tutorial pratici e self-service) e i video correlati mirano ad aiutare gli sviluppatori Google Cloud serverless a modernizzare le applicazioni guidandoli attraverso una o più migrazioni, principalmente abbandonando i servizi legacy. In questo modo le tue app saranno più portabili e avrai più opzioni e flessibilità, consentendoti di integrare e accedere a una gamma più ampia di prodotti Cloud e di eseguire più facilmente l'upgrade a release delle lingue più recenti. Pur concentrandosi inizialmente sui primi utenti di Cloud, principalmente sviluppatori di App Engine (ambiente standard), questa serie è sufficientemente ampia da includere altre piattaforme serverless come Cloud Functions e Cloud Run, o altrove, se applicabile.
Questo codelab ti insegna come eseguire la migrazione dall'archivio BLOB di App Engine a Cloud Storage. Esistono anche migrazioni implicite da:
- Frame web
webapp2
a Flask (trattato dal Modulo 1) - Da NDB di App Engine a Cloud NDB per l'accesso a Datastore (coperto dal Modulo 2)
- Python da 2 a 3 (l'app migrata è compatibile sia con Python 2 che 3)
Per informazioni più dettagliate, fai riferimento agli eventuali moduli di migrazione correlati.
Imparerai a utilizzare
- Aggiungi utilizzo dell'API/libreria App Engine Blobstore
- Archiviare i caricamenti degli utenti sul servizio Blobstore
- Preparati per il passaggio successivo della migrazione a Cloud Storage
Che cosa ti serve
- Un progetto piattaforma Google Cloud con un account di fatturazione Google Cloud attivo
- Competenze Python di base
- Conoscenza pratica dei comandi Linux più comuni
- Conoscenza di base dello sviluppo e del deployment delle app App Engine
- Un'app 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 giudichi la tua esperienza di 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 comporta la sostituzione delle dipendenze nei servizi in bundle legacy di App Engine, che consentono di spostare le app su un'altra piattaforma serverless Cloud o un'altra piattaforma di hosting, se lo desideri.
Questa migrazione richiede un po' più di impegno rispetto alle altre migrazioni di questa serie. Il Blobstore ha dipendenze rispetto al framework originale dell'app web ed è per questo che 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 continua a registrare le "visite" degli utenti finali e mostra i dieci più recenti, ma il codelab precedente (Modulo 15) ha aggiunto nuove funzionalità per consentire 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" la disattivazione. Indipendentemente dalla decisione dell'utente, nella pagina successiva viene visualizzato lo stesso output delle versioni precedenti dell'app, visualizzando le visite più recenti. Un'altra novità è che le visite con gli artefatti corrispondenti presentano una "vista" link per visualizzare l'elemento di una visita. Questo codelab implementa le migrazioni menzionate in precedenza mantenendo la funzionalità descritta.
3. Configurazione/pre-lavoro
Prima di passare alla 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 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. Ottieni app di esempio di riferimento
Uno dei prerequisiti di questo codelab è avere un'app di esempio funzionante del Modulo 15. Se non ce l'hai, puoi scaricarlo dal modulo 15 "INIZIA" cartella (link sotto). Questo codelab ti guida in ogni passaggio e si conclude con un codice simile a quello del modulo 16 "FINISH" .
- AVVIA: cartella Modulo 15 (Python 2)
- FINISH: cartella del modulo 16 (Python 2)
- Intero repository (per clonare o scaricare il file ZIP)
La directory dei file STARTing del modulo 15 dovrebbe essere simile alla seguente:
$ ls README.md app.yaml main-gcs.py main.py templates
Il file main-gcs.py
è una versione alternativa di main.py
rispetto al Modulo 15 che consente di selezionare un bucket Cloud Storage diverso da quello predefinito dell'URL assegnato a un'app in base all'ID progetto: PROJECT_ID
.appspot.com
. Se lo desideri, questo file non ha alcun ruolo in questo codelab (Modulo 16) ad eccezione di tecniche di migrazione simili.
3. (Ri)Esegui il deployment dell'app di base
I passaggi preliminari rimanenti da eseguire ora:
- Acquisisci 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 verificato che l'app del Modulo 15 funzioni, La pagina iniziale accoglie gli utenti con un modulo che richiede il caricamento di un file dell'artefatto visita insieme a un'opzione, "salta" pulsante, per disattivare:
Quando gli utenti caricano o saltano un file, l'app mostra le "visite più recenti" che già conosci. pagina:
Le visite contenenti un artefatto avranno una "visualizzazione" link a destra del timestamp della visita per visualizzare (o scaricare) l'elemento. Dopo aver verificato la funzionalità dell'app, puoi eseguire la migrazione dai servizi legacy di App Engine (webapp2, NDB, Blobstore) alle alternative contemporanee (Flask, Cloud NDB, Cloud Storage).
4. Aggiorna i file di configurazione
Per la versione aggiornata dell'app entrano in gioco tre file di configurazione. Le attività obbligatorie sono:
- Aggiorna le librerie di terze parti integrate necessarie in
app.yaml
e lascia la porta aperta per la migrazione a Python 3 - Aggiungi un valore
requirements.txt
, che specifichi tutte le librerie richieste che non sono integrate - Aggiungi
appengine_config.py
in modo che l'app supporti sia le librerie di terze parti integrate che non integrate
app.yaml
Modifica il file app.yaml
aggiornando la sezione libraries
. Rimuovi jinja2
e aggiungi grpcio
, setuptools
e ssl
. Scegli la versione più recente disponibile per tutte e tre le librerie. Aggiungi anche l'istruzione Python 3 runtime
, ma con un commento. Al termine, l'aspetto dovrebbe essere simile a questo (se hai selezionato Python 3.9):
PRIMA:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: jinja2
version: latest
DOPO:
#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, quindi non è necessario raggrupparle autonomamente. Abbiamo rimosso Jinja2 perché include Flask, che aggiungeremo al file reqs.txt. Ogni volta che vengono utilizzate librerie client di Google Cloud, come quelle per Cloud NDB e Cloud Storage, sono necessari grpcio e setuptools. Infine, Cloud Storage richiede la libreria SSL. L'istruzione di runtime commentata in alto serve per quando è tutto pronto per la portabilità dell'app in Python 3. Questo argomento verrà trattato alla fine del tutorial.
requirements.txt
Aggiungi un file requirements.txt
che richieda il framework Flask e le librerie client di Cloud NDB e Cloud Storage, nessuno dei quali è integrato. Crea il file con questi contenuti:
flask
google-cloud-ndb
google-cloud-storage
Il runtime Python 2 di App Engine richiede il raggruppamento autonomo delle librerie di terze parti non integrate, quindi esegui questo comando per installare queste librerie nella cartella lib:
pip install -t lib -r requirements.txt
Se hai sia Python 2 che 3 sulla tua macchina di sviluppo, potresti dover usare 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 creare autonomamente il bundle.
appengine_config.py
Aggiungi un file appengine_config.py
che supporti le 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 le app Python 2 della documentazione su App Engine e, in particolare, i contenuti di appengine_config.py
dovrebbero corrispondere a quelli del passaggio 5.
Il lavoro sui file di configurazione è stato completato, quindi passiamo all'applicazione.
5. Modifica i file delle applicazioni
Importazioni
Il primo insieme di modifiche per main.py
include la sostituzione di tutti gli elementi sostituiti. Ecco cosa cambierà:
webapp2
è stato sostituito da Flask- Invece di utilizzare Jinja2 di
webapp2_extras
, usa Jinja2 fornito con Flask - L'archivio BLOB e NDB di App Engine sono sostituiti da Cloud NDB e Cloud Storage
- I gestori Blobstore in
webapp
vengono sostituiti da una combinazione delle utilitàio
del modulo della libreria standard, Flask ewerkzeug
- Per impostazione predefinita, l'archivio BLOB scrive in un bucket Cloud Storage denominato in base all'URL dell'app (
PROJECT_ID.appspot.com
). Poiché è in corso la portabilità alla libreria client di Cloud Storage,google.auth
viene utilizzato per ottenere l'ID progetto in modo da specificare esattamente lo stesso nome di 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
Implementare le modifiche nell'elenco precedente sostituendo la sezione di importazione corrente in main.py
con lo snippet di codice riportato di seguito.
DOPO:
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'uso di Jinja2 da webapp2_extras
. Questo non è necessario perché Jinja2 viene fornito con Flask ed è il suo motore di modelli predefinito, quindi rimuovilo.
Sul lato del Modulo 16, crea un'istanza degli oggetti che non erano presenti nell'app precedente. Ciò include l'inizializzazione dell'app Flask e la creazione di client API per Cloud NDB e Cloud Storage. Infine, abbiamo creato il nome del bucket Cloud Storage, come descritto sopra nella sezione Importazioni. Ecco le fasi 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))
DOPO:
app = Flask(__name__)
ds_client = ndb.Client()
gcs_client = storage.Client()
_, PROJECT_ID = google.auth.default()
BUCKET = '%s.appspot.com' % PROJECT_ID
Aggiorna accesso a Datastore
Cloud NDB è per lo più compatibile con l'NDB di App Engine. Una differenza già contemplata è la necessità di un client API. Un altro è che quest'ultimo richiede che l'accesso a Datastore sia controllato dal gestore di contesto Python del client API. In sostanza, questo significa che tutte le chiamate di accesso a Datastore che utilizzano la libreria client di Cloud NDB possono avvenire solo all'interno dei blocchi Python with
.
Questa è una modifica: l'altra è che l'archivio BLOB e i suoi oggetti, ad esempio BlobKey
non sono supportati da Cloud Storage, quindi modifica file_blob
in ndb.StringProperty
. Di seguito sono riportate la classe del modello dei 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)
DOPO:
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 caricamento
I gestori in webapp2
sono classi mentre svolgono funzioni in Flask. Invece di un metodo verbale HTTP, Flask utilizza il verbo per decorare la funzione. L'archivio BLOB e i relativi gestori webapp
sono sostituiti dalla funzionalità di Cloud Storage, nonché da Flask e dalle sue 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)
DOPO:
@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 relative a questo aggiornamento:
- Anziché
blob_id
, gli elementi dei file sono ora identificati dal nome del file (fname
), se presente, e daNone
in caso contrario (l'utente ha disattivato il caricamento di un file). - I gestori dell'archivio BLOB hanno astrae il processo di caricamento dagli utenti, ma Cloud Storage non lo fa. Di conseguenza, 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()
) webapp2
utilizza una tabella di routing nella parte inferiore del file dell'applicazione, mentre le route Flask si trovano in ogni gestore decorato.- Entrambi i gestori aggregano la loro funzionalità reindirizzando alla home page (
/
), preservando la richiestaPOST
con un codice restituito HTTP 307.
Gestore dei download
L'aggiornamento del gestore dei download segue uno schema simile a quello del gestore del caricamento, ma c'è molto meno codice da esaminare. Sostituisci l'archivio BLOB e la funzionalità 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)
DOPO:
@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:
- Ancora una volta, Flask decora le funzioni dei gestori con la rispettiva route, mentre
webapp
la esegue in una tabella di routing nella parte inferiore, quindi riconosce la sintassi di corrispondenza dei pattern di quest'ultima('/view/([^/]+)?'
) rispetto a quella di Flask ('/view/<path:fname>'
). - Come per il gestore di caricamento, è richiesto un po' più di lavoro da parte di Cloud Storage per la funzionalità astratta dai gestori dell'archivio BLOB, ovvero l'identificazione del file (blob) in questione e il download esplicito della singola chiamata al metodo
send_blob()
del gestore binario o dell'archivio BLOB. - In entrambi i casi, se non viene trovato un artefatto, all'utente viene restituito un errore HTTP 404.
Gestore principale
Le modifiche finali all'applicazione principale avvengono nel gestore principale. I metodi verbo HTTP webapp2
sono sostituiti da un'unica funzione che ne combina la 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)
DOPO:
@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é separare i metodi get()
e post()
, si tratta essenzialmente di un'istruzione if-else
in root()
. Inoltre, poiché root()
è una singola funzione, esiste una sola chiamata per eseguire il rendering del modello sia per GET
sia per POST
, mentre in webapp2
non è possibile.
Ecco una rappresentazione grafica di questa seconda e ultima serie di modifiche a main.py
:
(Facoltativo) "Miglioramento" della compatibilità con le versioni precedenti
Quindi la soluzione creata sopra funziona perfettamente... ma solo se stai iniziando da zero e non hai file creati da Blobstore. Poiché abbiamo aggiornato l'app per identificare i file per nome invece che per BlobKey
, l'app del modulo 16 completata così com'è non sarà in grado di visualizzare i file dell'archivio BLOB. In altre parole, durante questa migrazione abbiamo apportato una modifica incompatibile con le versioni precedenti. Ora presentiamo una versione alternativa di main.py
denominata main-migrate.py
(trovata nel repository) che tenta di colmare questo divario.
La prima "estensione" per supportare i file creati da Blobstore è un modello dei dati che include un valore BlobKeyProperty
(oltre a un StringProperty
per i file creati in 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 un po' 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()
DOPO:
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()
Durante il recupero delle 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)
DOPO:
@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)
Ora conferma l'esistenza di file_blob
o file_gcs
(o nessuno dei due). Se è disponibile un file, scegli quello esistente e utilizza questo identificatore (BlobKey
per i file creati dall'archivio BLOB o il nome file per i file creati da Cloud Storage). Quando diciamo "File creati in Cloud Storage", intendiamo i file creati utilizzando la libreria client di Cloud Storage. Anche l'archivio BLOB scrive in Cloud Storage, ma in questo caso si tratta di file creati da Blobstore.
Ora, cosa ancora più importante, qual è la funzione etl_visits()
utilizzata per normalizzare o ETL (estrarre, trasformare e caricare) i 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 sembra quello che ti aspettavi: il codice si ripete in tutte le visite e, per ogni visita, esamina i dati del visitatore e del timestamp, dopodiché verifica se file_gcs
o file_blob
esistono e, in tal caso, ne sceglie una (o None
se nessuno dei due esiste).
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 file di supporto creati sia da Blobstore sia Cloud Storage, dai un'occhiata a main-migrate.py
come esempio di come gestire uno scenario come 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à per la modernizzazione delle app reali con dati reali.
6. Riepilogo/Pulizia
In questa sezione si conclude questo codelab eseguendo il deployment dell'app e verificando che funzioni come previsto e in qualsiasi output riportato. Dopo la convalida dell'app, esegui tutti i passaggi di pulizia e considera i passaggi successivi.
Esegui il deployment e verifica l'applicazione
Prima di eseguire nuovamente il deployment dell'app, assicurati di eseguire pip install -t lib -r requirements.txt
per inserire le librerie di terze parti auto-in bundle nella cartella lib. Se vuoi eseguire la soluzione compatibile con le versioni precedenti, rinomina prima main-migrate.py
come 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 il seguente aspetto:
Complimenti per aver completato questo codelab per la sostituzione dell'archivio BLOB di App Engine con Cloud Storage, dell'NDB di App Engine con Cloud NDB e di webapp2
con Flask. Il codice dovrebbe corrispondere al contenuto della cartella FINISH (Modulo 16). In questa cartella è presente anche l'alternativa main-migrate.py
.
"Migrazione" Python 3
L'istruzione Python 3 runtime
commentato nella parte superiore di app.yaml
è tutto ciò che serve per portare questa app in Python 3. Il codice sorgente stesso è già compatibile con Python 3, quindi non sono necessarie modifiche. Per eseguire il deployment come app Python 3, esegui questi passaggi:
- Rimuovi il commento dall'istruzione Python 3
runtime
nella parte superiore diapp.yaml
. - Elimina tutte le altre righe in
app.yaml
. - Elimina il file
appengine_config.py
. (non utilizzato nel runtime di Python 3) - Elimina la cartella
lib
, se esistente. (non necessario con il runtime Python 3)
Esegui la pulizia
Generale
Se per il momento hai finito, ti consigliamo di disabilitare l'app App Engine per evitare di incorrere in fatturazione. Tuttavia, se desideri eseguire altri test o sperimentarli, la piattaforma App Engine ha una quota senza costi, pertanto, se non superi il livello di utilizzo, non ti verrà addebitato alcun costo. Questo riguarda il computing, ma potrebbero essere addebitati costi anche per i servizi App Engine pertinenti, quindi consulta la pagina dei prezzi per ulteriori informazioni. Se la migrazione coinvolge altri servizi Cloud, questi vengono fatturati separatamente. In entrambi i casi, se applicabile, consulta la sezione "Specifici di questo codelab" di seguito.
Per garantire la piena divulgazione, il deployment su una piattaforma di serverless computing di Google Cloud come App Engine comporta costi minori di build e archiviazione. Cloud Build e Cloud Storage hanno una quota senza costi specifica. Lo spazio di archiviazione dell'immagine esaurisce una parte della quota. Tuttavia, potresti risiedere in una regione che non ha un livello senza costi, quindi tieni presente l'utilizzo dello spazio di archiviazione per ridurre al minimo i costi potenziali. "cartelle" specifiche di Cloud Storage da esaminare includono:
console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/images
console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com
- I link allo spazio di archiviazione riportati sopra dipendono dalla tua
PROJECT_ID
e dalla tua *LOC
*azione, ad esempio "us
" se la tua app è ospitata negli Stati Uniti.
Se invece non intendi continuare con questa applicazione o con altri codelab di migrazione correlati e vuoi eliminare tutto completamente, chiudi il progetto.
Specifico di questo codelab
I servizi elencati di seguito sono esclusivi per questo codelab. Per ulteriori informazioni, fai riferimento alla documentazione di ciascun prodotto:
- Il servizio Blobstore di App Engine rientra in Quote e limiti per i dati archiviati, quindi consultali e consulta la pagina dei prezzi dei servizi in bundle legacy.
- Cloud Storage prevede un livello senza costi per regioni specifiche; consulta anche la pagina relativa ai prezzi generali per ulteriori informazioni.
- Il servizio App Engine Datastore è fornito da Cloud Datastore (Cloud Firestore in modalità Datastore), che prevede anche un livello senza costi; consulta la pagina relativa ai prezzi per ulteriori informazioni."
Tieni presente che se hai eseguito la migrazione dal modulo 15 al 16, continuerai ad avere dati in Blobstore e, per questo motivo, includiamo le informazioni sui prezzi riportate sopra.
Passaggi successivi
Oltre a questo tutorial, altri moduli di migrazione che si concentrano sull'abbandono dei servizi in bundle legacy da prendere in considerazione includono:
- Modulo 2: migrazione da App Engine
ndb
a Cloud NDB - Moduli 7-9: migrazione dalle attività di push della coda di attività di App Engine a Cloud Tasks
- Moduli 12-13: migrazione da App Engine Memcache a Cloud Memorystore
- Moduli 18-19: migrazione dalla coda di attività di App Engine (attività pull) a Cloud Pub/Sub
App Engine non è più l'unica piattaforma serverless in Google Cloud. Se hai un'app App Engine di piccole dimensioni o con funzionalità limitate e vuoi convertirla in un microservizio autonomo oppure vuoi suddividere un'app monolitica in più componenti riutilizzabili, questi sono ottimi motivi per passare a Cloud Functions. Se la containerizzazione è diventata parte del flusso di lavoro per lo sviluppo delle applicazioni, in particolare se è costituita da una pipeline CI/CD (integrazione continua/distribuzione continua o deployment), valuta la possibilità di eseguire la migrazione a Cloud Run. Questi scenari sono trattati nei seguenti moduli:
- Eseguire la migrazione da App Engine a Cloud Functions: consulta il Modulo 11
- Esegui la migrazione da App Engine a Cloud Run: consulta il Modulo 4 per containerizzare la tua app con Docker oppure il Modulo 5 per eseguire questa operazione senza container, conoscenze di Docker o
Dockerfile
Il passaggio a un'altra piattaforma serverless è facoltativo e prima di apportare modifiche ti consigliamo di valutare le opzioni migliori per le tue app e i tuoi casi d'uso.
Indipendentemente dal modulo di migrazione successivo, sarà possibile accedere a tutti i contenuti di Serverless Migration Station (codelab, video, codice sorgente [se disponibile]) nel relativo repository open source. L'elemento README
del repository fornisce anche indicazioni sulle migrazioni da prendere in considerazione e su eventuali "ordine" pertinenti dei Moduli di migrazione.
7. Risorse aggiuntive
Problemi/feedback del codelab
Se riscontri problemi con questo codelab, cercali prima di procedere con l'invio. Link per eseguire ricerche e creare nuovi problemi:
Risorse di migrazione
I link alle cartelle repository per il modulo 15 (START) e il modulo 16 (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 |
Modulo 15 | N/A | |
Modulo 16 (questo codelab) | (come Python 2) |
Risorse online
Di seguito sono riportate alcune risorse online che potrebbero essere pertinenti per questa esercitazione:
Blobstore e Cloud Storage di App Engine
- 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 Python 2 App Engine (ambiente standard)
- Utilizzo delle librerie integrate di App Engine in App Engine per Python 2
- Runtime Python 3 per App Engine (ambiente standard)
- Differenze tra Python 2 e 3 runtime App Engine (ambiente standard)
- Guida alla migrazione di Python da 2 a 3 per App Engine (ambiente standard)
- Informazioni su prezzi e quote di App Engine
- Lancio della piattaforma App Engine di seconda generazione (2018)
- Confronto tra primo e piattaforme di seconda generazione
- Assistenza a lungo termine per i runtime legacy
- Repository di esempi di migrazione della documentazione
- Repository di esempio sulla migrazione dei contributi della community
Altre informazioni sul cloud
- Python su Google Cloud Platform
- Librerie client di Google Cloud per Python
- "Sempre senza costi" di Google Cloud livello
- Google Cloud SDK (strumento a riga di comando
gcloud
) - Tutta la documentazione di Google Cloud
Python
- Sistemi di creazione di modelli di Django e Jinja2
- Framework web
webapp2
- Documentazione di
webapp2
webapp2_extras
linkwebapp2_extras
Documentazione di Jinja2- Framework web flessibile
Video
- Stazione di migrazione serverless
- Esplorazioni serverless
- Iscriviti a Google Cloud Tech
- Iscriviti a Google Developers
Licenza
Questo lavoro è concesso in licenza ai sensi di una licenza Creative Commons Attribution 2.0 Generic.