Eseguire la migrazione da App Engine Memcache a Cloud Memorystore (modulo 13)

1. Panoramica

La serie di codelab Serverless Migration Station (esercitazioni pratiche e autonome) e i video correlati hanno lo scopo di aiutare gli sviluppatori serverless di Google Cloud a modernizzare le loro applicazioni guidandoli attraverso una o più migrazioni, principalmente abbandonando i servizi legacy. In questo modo, le tue app sono più portatili e hai più opzioni e flessibilità, il che ti consente di integrarti e accedere a una gamma più ampia di prodotti cloud e di eseguire più facilmente l'upgrade alle versioni più recenti del linguaggio. 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 altrove, se applicabile.

Lo scopo di questo codelab è mostrare agli sviluppatori di App Engine Python 2 come eseguire la migrazione da App Engine Memcache a Cloud Memorystore (per Redis). Esiste anche una migrazione implicita da App Engine ndb a Cloud NDB, ma questa è trattata principalmente nel codelab del modulo 2. Consulta questa risorsa per informazioni più dettagliate.

Imparerai a utilizzare

  • Configura un'istanza Cloud Memorystore (dalla console Cloud o dallo strumento gcloud)
  • Configura un connettore di accesso VPC serverless (da Cloud Console o dallo strumento gcloud)
  • Esegui la migrazione da App Engine Memcache a Cloud Memorystore
  • Implementa la memorizzazione nella cache con Cloud Memorystore in un'app di esempio
  • Migrazione da App Engine ndb a Cloud NDB

Che cosa ti serve

Sondaggio

Come utilizzerai questo tutorial?

Solo lettura Lettura e completamento degli esercizi

Come valuteresti la tua esperienza con Python?

Principiante Intermedio Avanzato

Come valuti la tua esperienza di utilizzo dei servizi Google Cloud?

Principiante Intermedio Avanzato

2. Sfondo

Questo codelab mostra come eseguire la migrazione di un'app di esempio da App Engine Memcache (e NDB) a Cloud Memorystore (e Cloud NDB). Questa procedura prevede la sostituzione delle dipendenze dai servizi integrati di App Engine, rendendo le tue app più portatili. Puoi scegliere di rimanere su App Engine o prendere in considerazione il passaggio a una delle alternative descritte in precedenza.

Questa migrazione richiede più impegno rispetto alle altre di questa serie. La sostituzione consigliata per App Engine Memcache è Cloud Memorystore, un servizio di memorizzazione nella cache basato sul cloud completamente gestito. Memorystore supporta una coppia di motori di memorizzazione nella cache open source popolari, Redis e Memcached. Questo modulo di migrazione utilizza Cloud Memorystore for Redis. Per saperne di più, consulta la panoramica di Memorystore e Redis.

Poiché Memorystore richiede un server in esecuzione, è necessario anche Cloud VPC. In particolare, deve essere creato un connettore di accesso VPC serverless in modo che l'app App Engine possa connettersi all'istanza Memorystore tramite il relativo indirizzo IP privato. Al termine di questo esercizio, avrai aggiornato l'app in modo che, pur comportandosi come prima, Cloud Memorystore sia il servizio di memorizzazione nella cache, sostituendo il servizio Memcache di App Engine.

Questo tutorial inizia con l'app di esempio del modulo 12 in Python 2, seguito da un upgrade secondario facoltativo a Python 3. Se hai già familiarità con l'accesso ai servizi in bundle di App Engine da Python 3 tramite l'SDK App Engine per Python 3, puoi iniziare con la versione Python 3 dell'app di esempio del modulo 12. In questo modo, l'utilizzo dell'SDK verrà rimosso, poiché Memorystore non è un servizio in bundle di App Engine. L'apprendimento dell'utilizzo dell'SDK App Engine Python 3 non rientra nell'ambito di questo tutorial.

Questo tutorial prevede i seguenti passaggi chiave:

  1. Configurazione/preparazione
  2. Configura i servizi di memorizzazione nella cache
  3. Aggiorna i file di configurazione
  4. Aggiorna l'applicazione principale

3. Configurazione/preparazione

Prepara il progetto cloud

Ti consigliamo di riutilizzare lo stesso progetto che hai utilizzato per completare il codelab del modulo 12. In alternativa, puoi creare un nuovo progetto o riutilizzarne uno esistente. Ogni codelab di questa serie ha un "INIZIO" (il codice di base da cui partire) e una "FINE" (l'app di cui è stata eseguita la migrazione). Il codice FINISH viene fornito per consentirti di confrontare le tue soluzioni con le nostre in caso di problemi. Se qualcosa va storto, puoi sempre ripristinare lo stato iniziale. Questi punti di controllo sono progettati per assicurarti di imparare a eseguire le migrazioni.

Qualunque sia il progetto Cloud che utilizzi, assicurati che abbia un account di fatturazione attivo. Assicurati inoltre che App Engine sia abilitato. Esamina e assicurati di comprendere le implicazioni generali dei costi derivanti da questi tutorial. A differenza di altri codelab di questa serie, questo utilizza risorse cloud che non hanno un livello senza costi, pertanto per completare l'esercizio verranno sostenuti alcuni costi. Verranno fornite informazioni più specifiche sui costi, insieme a consigli per ridurre l'utilizzo, incluse istruzioni alla fine su come rilasciare le risorse per ridurre al minimo gli addebiti di fatturazione.

Ottieni l'app di esempio di base

A partire dal codice di base del modulo 12, questo codelab ti guida passo passo nella migrazione. Al termine, otterrai un'app del modulo 13 funzionante che assomiglia molto al codice in una delle cartelle FINISH. Ecco le risorse:

La cartella START deve contenere i seguenti file:

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

Se inizi dalla versione Python 2, ci sarà anche un file appengine_config.py ed eventualmente una cartella lib se hai completato il codelab del modulo 12.

(Esegui di nuovo il deployment dell'app del modulo 12

I passaggi preparatori rimanenti:

  1. Riacquisisci familiarità con lo strumento a riga di comando gcloud (se necessario)
  2. (Esegui di nuovo il) deployment del codice del Modulo 12 in App Engine (se necessario)

Gli utenti di Python 2 devono eliminare e reinstallare la cartella lib con questi comandi:

rm -rf ./lib; pip install -t lib -r requirements.txt                

Ora tutti (utenti di Python 2 e 3) devono caricare il codice su App Engine con questo comando:

gcloud app deploy                

Una volta eseguito il deployment, verifica che l'app abbia lo stesso aspetto e funzioni come l'app del modulo 12, un'app web che monitora le visite e le memorizza nella cache per lo stesso utente per un'ora:

dfe56a02ae59ddd8.png

Poiché le visite più recenti vengono memorizzate nella cache, gli aggiornamenti della pagina dovrebbero caricarsi abbastanza rapidamente.

4. Configura i servizi di memorizzazione nella cache

Cloud Memorystore non è serverless. È necessaria un'istanza, in questo caso una che esegue Redis. A differenza di Memcache, Memorystore è un prodotto Cloud autonomo e non dispone di un livello senza costi, quindi assicurati di controllare le informazioni sui prezzi di Memorystore for Redis prima di procedere. Per ridurre al minimo i costi di questo esercizio, ti consigliamo la quantità minima di risorse per operare: un livello di servizio Basic e una capacità di 1 GB.

L'istanza Memorystore si trova su una rete diversa rispetto alla tua app App Engine (istanze), motivo per cui è necessario creare un connettore di accesso VPC serverless in modo che App Engine possa accedere alle tue risorse Memorystore. Per ridurre al minimo i costi VPC, scegli il tipo di istanza (f1-micro) e il numero minimo di istanze da richiedere (suggeriamo un minimo di 2 e un massimo di 3). Consulta anche la pagina con le informazioni sui prezzi di VPC.

Ripetiamo questi consigli per ridurre i costi mentre ti guidiamo nella creazione di ogni risorsa richiesta. Inoltre, quando crei risorse Memorystore e VPC in Cloud Console, nell'angolo in alto a destra viene visualizzato il calcolatore dei prezzi per ogni prodotto, che ti fornisce una stima dei costi mensili (vedi l'illustrazione di seguito). Questi valori vengono modificati automaticamente se cambi le opzioni. Ecco cosa dovresti vedere:

7eb35ebf7248c010.png

Entrambe le risorse sono obbligatorie e non importa quale crei per prima. Se crei prima l'istanza Memorystore, la tua app App Engine non può raggiungerla senza il connettore VPC. Allo stesso modo, se crei prima il connettore VPC, non c'è nulla su quella rete VPC con cui la tua app App Engine possa comunicare. In questo tutorial viene creata prima l'istanza Memorystore e poi il connettore VPC.

Una volta che entrambe le risorse sono online, aggiungi le informazioni pertinenti a app.yaml in modo che la tua app possa accedere alla cache. Puoi anche consultare le guide di Python 2 o Python 3 nella documentazione ufficiale. Ti consigliamo di consultare anche la guida alla memorizzazione nella cache dei dati nella pagina di migrazione di Cloud NDB ( Python 2 o Python 3).

Crea un'istanza di Cloud Memorystore

Poiché Cloud Memorystore non ha un livello senza costi, ti consigliamo di allocare la quantità minima di risorse per completare il codelab. Puoi ridurre al minimo i costi utilizzando queste impostazioni:

  • Seleziona il livello di servizio più basso: Basic (impostazione predefinita della console: "Standard", impostazione predefinita di gcloud: "Basic").
  • Scegli la quantità minima di spazio di archiviazione: 1 GB (valore predefinito della console: 16 GB, valore predefinito di gcloud: 1 GB).
  • In genere, le versioni più recenti di qualsiasi software richiedono la quantità maggiore di risorse, ma anche la selezione della versione più vecchia non è consigliata. La seconda versione più recente è attualmente la versione Redis 5.0 (impostazione predefinita della console: 6.x)

Tenendo presente queste impostazioni, la sezione successiva ti guiderà nella creazione dell'istanza dalla console Cloud. Se preferisci farlo dalla riga di comando, vai avanti.

Dalla console Cloud

Vai alla pagina Cloud Memorystore nella console Cloud (potrebbe esserti chiesto di inserire i dati di fatturazione). Se non hai ancora attivato Memorystore, ti verrà chiesto di farlo:

68318997e3105db6.png

Una volta attivato (e possibilmente insieme alla fatturazione), si aprirà la dashboard di Memorystore. Qui puoi visualizzare tutte le istanze create nel tuo progetto. Il progetto mostrato di seguito non ne ha, quindi è per questo che vedi "Nessuna riga da visualizzare". Per creare un'istanza Memorystore, fai clic su Crea istanza in alto:

63547aa575838a36.png

Questa pagina include un modulo da compilare con le impostazioni desiderate per creare l'istanza Memorystore:

b77d927287fdf4c7.png

Per contenere i costi di questo tutorial e della relativa app di esempio, segui i consigli illustrati in precedenza. Dopo aver effettuato le selezioni, fai clic su Crea. Il processo di creazione richiede diversi minuti. Al termine, copia l'indirizzo IP e il numero di porta dell'istanza da aggiungere a app.yaml.

Dalla riga di comando

Sebbene la creazione di istanze Memorystore da Cloud Console sia visivamente informativa, alcuni preferiscono la riga di comando. Prima di procedere, assicurati di aver installato e inizializzato gcloud.

Come per la console Cloud, Cloud Memorystore for Redis deve essere abilitato. Esegui il comando gcloud services enable redis.googleapis.com e attendi il completamento, come in questo esempio:

$ gcloud services enable redis.googleapis.com
Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.

Se il servizio è già stato attivato, l'esecuzione (di nuovo) del comando non ha effetti collaterali (negativi). Con il servizio abilitato, creiamo un'istanza Memorystore. Il comando è il seguente:

gcloud redis instances create NAME --redis-version VERSION \
    --region REGION --project PROJECT_ID

Scegli un nome per la tua istanza Memorystore. Questo lab utilizza "demo-ms" come nome e "my-project" come ID progetto. La regione di questa app di esempio è us-central1 (la stessa di us-central), ma puoi utilizzarne una più vicina a te se la latenza è un problema. Devi selezionare la stessa regione dell'app App Engine. Puoi selezionare la versione di Redis che preferisci, ma stiamo utilizzando la versione 5 come consigliato in precedenza. Date queste impostazioni, questo è il comando da eseguire (insieme all'output associato):

$ gcloud redis instances create demo-ms --region us-central1 \
    --redis-version redis_5_0 --project my-project

Create request issued for: [demo-ms]
Waiting for operation [projects/my-project/locations/us-central1/operations/operation-xxxx] to complete...done.
Created instance [demo-ms].

A differenza delle impostazioni predefinite della console Cloud, gcloud utilizza risorse minime per impostazione predefinita. Il risultato è che né il livello di servizio né la quantità di spazio di archiviazione erano richiesti in questo comando. La creazione di un'istanza Memorystore richiede diversi minuti. Al termine, annotati l'indirizzo IP e il numero di porta dell'istanza, in quanto verranno aggiunti a app.yaml a breve.

Conferma la creazione dell'istanza

Dalla console Cloud o dalla riga di comando

Indipendentemente dal fatto che tu abbia creato l'istanza dalla console Cloud o dalla riga di comando, puoi verificare che sia disponibile e pronta per l'uso con questo comando: gcloud redis instances list --region REGION

Ecco il comando per controllare le istanze nella regione us-central1 insieme all'output previsto che mostra l'istanza appena creata:

$ gcloud redis instances list --region us-central1
INSTANCE_NAME  VERSION    REGION       TIER   SIZE_GB  HOST         PORT  NETWORK  RESERVED_IP     STATUS  CREATE_TIME
demo-ms        REDIS_5_0  us-central1  BASIC  1        10.aa.bb.cc  6379  default  10.aa.bb.dd/29  READY   2022-01-28T09:24:45

Quando ti viene chiesto di inserire le informazioni sull'istanza o di configurare l'app, assicurati di utilizzare HOST e PORT (non RESERVED_IP). La dashboard di Cloud Memorystore in Cloud Console dovrebbe ora mostrare l'istanza:

c5a6948ec1c056ed.png

Dalla macchina virtuale Compute Engine

Se hai una macchina virtuale (VM) Compute Engine, puoi anche inviare comandi diretti all'istanza Memorystore da una VM per verificare che funzioni. Tieni presente che l'utilizzo di una VM potrebbe comportare costi associati indipendenti dalle risorse che stai già utilizzando.

Crea un connettore di accesso VPC serverless

Come per Cloud Memorystore, puoi creare il connettore VPC serverless in Cloud Console o dalla riga di comando. Allo stesso modo, Cloud VPC non ha un livello senza costi, pertanto ti consigliamo di allocare la quantità minima di risorse per completare il codelab al fine di ridurre al minimo i costi. Questo risultato può essere ottenuto con le seguenti impostazioni:

  • Seleziona il numero massimo di istanze più basso: 3 (valore predefinito di console e gcloud: 10)
  • Scegli il tipo di macchina meno costoso: f1-micro (impostazione predefinita della console: e2-micro, nessuna impostazione predefinita per gcloud)

La sezione successiva ti guiderà nella creazione del connettore dalla console Cloud utilizzando le impostazioni VPC Cloud riportate sopra. Se preferisci farlo dalla riga di comando, vai alla sezione successiva.

Dalla console Cloud

Vai alla pagina "Accesso VPC serverless" di Cloud Networking nella console Cloud (potrebbe esserti chiesto di inserire i dati di fatturazione). Se non hai ancora abilitato l'API, ti verrà chiesto di farlo:

e3b9c0651de25e97.png

Una volta abilitata l'API (e possibilmente la fatturazione), visualizzerai la dashboard con tutti i connettori VPC creati. Il progetto utilizzato nello screenshot riportato di seguito non ne ha, perciò viene visualizzato il messaggio "Nessuna riga da visualizzare". Nella console, fai clic su Crea connettore in alto:

b74b49b9d73b7dcf.png

Compila il modulo con le impostazioni desiderate:

6b26b2aafa719f73.png

Scegli le impostazioni appropriate per le tue applicazioni. Per questo tutorial e la sua app di esempio con esigenze minime, è opportuno ridurre al minimo i costi, quindi segui i consigli trattati in precedenza. Dopo aver effettuato le selezioni, fai clic su Crea. Il provisioning di un connettore VPC richiede alcuni minuti.

Dalla riga di comando

Prima di creare un connettore VPC, abilita l'API Serverless VPC Access. Dovresti vedere un output simile dopo aver eseguito il seguente comando:

$ gcloud services enable vpcaccess.googleapis.com
Operation "operations/acf.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.

Con l'API abilitata, viene creato un connettore VPC con un comando simile al seguente:

gcloud compute networks vpc-access connectors create CONNECTOR_NAME \
    --range 10.8.0.0/28 --region REGION --project PROJECT_ID

Scegli un nome per il connettore e un indirizzo IP iniziale del blocco CIDR /28 inutilizzato. Questo tutorial si basa sulle seguenti ipotesi:

  • ID progetto: my-project
  • Nome connettore VPC: demo-vpc
  • Istanze minime: 2 (valore predefinito) e istanze massime: 3
  • Tipo di istanza: f1-micro
  • Regione: us-central1
  • Blocco CIDR IPv4: 10.8.0.0/28 (come consigliato nella console cloud)

Se esegui il seguente comando tenendo presente le ipotesi precedenti, l'output dovrebbe essere simile a quello riportato di seguito:

$ gcloud compute networks vpc-access connectors create demo-vpc \
    --max-instances 3 --range 10.8.0.0/28 --machine-type f1-micro \
    --region us-central1  --project my-project

Create request issued for: [demo-vpc]
Waiting for operation [projects/my-project/locations/us-central1/operations/xxx] to complete...done.
Created connector [demo-vpc].

Il comando precedente omette la specifica dei valori predefiniti, ad esempio un numero minimo di istanze pari a 2 e una rete denominata default. La creazione di un connettore VPC richiede alcuni minuti.

Conferma la creazione del connettore

Al termine della procedura, esegui il seguente comando gcloud, supponendo che si tratti della regione us-central1, per confermare che sia stato creato e pronto per l'uso:

$ gcloud compute networks vpc-access connectors list --region us-central1
CONNECTOR_ID  REGION       NETWORK  IP_CIDR_RANGE  SUBNET  SUBNET_PROJECT  MIN_THROUGHPUT  MAX_THROUGHPUT  STATE
demo-vpc      us-central1  default  10.8.0.0/28                            200             300             READY

Analogamente, la dashboard ora dovrebbe mostrare il connettore appena creato:

e03db2c8140ed014.png

Prendi nota dell'ID progetto Cloud, del nome del connettore VPC e della regione.

Ora che hai creato le risorse Cloud aggiuntive necessarie, tramite la riga di comando o nella console, è il momento di aggiornare la configurazione dell'applicazione per supportarne l'utilizzo.

5. Aggiorna i file di configurazione

Il primo passaggio consiste nell'apportare tutti gli aggiornamenti necessari ai file di configurazione. L'obiettivo principale di questo codelab è aiutare gli utenti di Python 2 a eseguire la migrazione. Tuttavia, in ogni sezione riportata di seguito, i contenuti vengono solitamente seguiti da informazioni sul porting a Python 3.

requirements.txt

In questa sezione, aggiungiamo pacchetti per supportare Cloud Memorystore e Cloud NDB. Per Cloud Memorystore for Redis, è sufficiente utilizzare il client Redis standard per Python (redis), poiché non esiste una libreria client Cloud Memorystore in sé. Aggiungi sia redis che google-cloud-ndb a requirements.txt, unendo flask del Modulo 12:

flask
redis
google-cloud-ndb

Questo file requirements.txt non include numeri di versione, il che significa che sono selezionate le versioni più recenti. Se si verificano incompatibilità, specifica i numeri di versione per bloccare le versioni funzionanti.

app.yaml

Nuove sezioni da aggiungere

Il runtime Python 2 di App Engine richiede pacchetti di terze parti specifici quando si utilizzano le API Cloud come Cloud NDB, ovvero grpcio e setuptools. Gli utenti di Python 2 devono elencare le librerie integrate come queste insieme a una versione disponibile in app.yaml. Se non hai ancora una sezione libraries, creane una e aggiungi entrambe le librerie come segue:

libraries:
- name: grpcio
  version: latest
- name: setuptools
  version: latest

Quando esegui la migrazione della tua app, potrebbe già avere una sezione libraries. Se è così e mancano sia grpcio che setuptools, aggiungili alla sezione libraries esistente.

Successivamente, la nostra app di esempio ha bisogno delle informazioni sull'istanza Cloud Memorystore e sul connettore VPC, quindi aggiungi le due nuove sezioni seguenti a app.yaml indipendentemente dal runtime Python che utilizzi:

env_variables:
    REDIS_HOST: 'YOUR_REDIS_HOST'
    REDIS_PORT: 'YOUR_REDIS_PORT'

vpc_access_connector:
    name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR

Per quanto riguarda gli aggiornamenti obbligatori, è tutto. Il tuo app.yaml aggiornato dovrebbe ora avere questo 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

env_variables:
    REDIS_HOST: 'YOUR_REDIS_HOST'
    REDIS_PORT: 'YOUR_REDIS_PORT'

vpc_access_connector:
    name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR

Di seguito è riportato un "prima e dopo" che illustra gli aggiornamenti da applicare a app.yaml:

ec2bb027a67debb6.png

*Differenze di Python 3

Questa sezione è facoltativa e solo se esegui il porting a Python 3. Per farlo, devi apportare una serie di modifiche alla configurazione di Python 2. Salta questa sezione se al momento non esegui l'upgrade.

threadsafeapi_version vengono utilizzati per il runtime Python 3, quindi elimina entrambe le impostazioni. L'ultimo runtime di App Engine non supporta le librerie di terze parti integrate né la copia di librerie non integrate. L'unico requisito per i pacchetti di terze parti è elencarli in requirements.txt. Di conseguenza, l'intera sezione libraries di app.yaml può essere eliminata.

Successivamente, il runtime Python 3 richiede l'utilizzo di framework web che eseguono il proprio routing, motivo per cui abbiamo mostrato agli sviluppatori come eseguire la migrazione da webp2 a Flask nel Modulo 1. Di conseguenza, tutti i gestori di script devono essere modificati in auto. Poiché questa app non gestisce file statici, è "inutile" avere gestori elencati (poiché sono tutti auto), quindi è possibile rimuovere anche l'intera sezione handlers. Di conseguenza, il nuovo app.yaml abbreviato e modificato per Python 3 dovrebbe essere abbreviato in questo modo:

runtime: python39

env_variables:
    REDIS_HOST: 'YOUR_REDIS_HOST'
    REDIS_PORT: 'YOUR_REDIS_PORT'

vpc_access_connector:
    name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR

Riepilogo delle differenze in app.yaml durante il porting a Python 3:

  • Eliminare le impostazioni di threadsafe e api_version
  • Elimina la sezione libraries
  • Elimina la sezione handlers (o solo i gestori script se la tua app pubblica file statici)

Sostituisci i valori

I valori nelle nuove sezioni per Memorystore e il connettore VPC sono solo segnaposto. Sostituisci i valori in maiuscolo (YOUR_REDIS_HOST, YOUR_REDIS_PORT, PROJECT_ID, REGION, CONNECTOR_NAME) con i valori salvati quando hai creato queste risorse in precedenza. Per quanto riguarda l'istanza Memorystore, assicurati di utilizzare HOST (non RESERVED_IP) e PORT. Ecco un modo rapido da riga di comando per ottenere HOST e PORT, supponendo che il nome dell'istanza sia demo-ms e che REGION sia us-central1:

$ gcloud redis instances describe demo-ms --region us-central1 \
    --format "value(host,port)"
10.251.161.51   6379

Se l'indirizzo IP della nostra istanza Redis di esempio era 10.10.10.10 utilizzando la porta 6379 nel nostro progetto my-project situato nella regione us-central1 con un nome di connettore VPC demo-vpc, queste sezioni in app.yaml avranno il seguente aspetto:

env_variables:
    REDIS_HOST: '10.10.10.10'
    REDIS_PORT: '6379'

vpc_access_connector:
    name: projects/my-project/locations/us-central1/connectors/demo-vpc

Crea o aggiorna appengine_config.py

Aggiungere il supporto per le librerie di terze parti integrate

Proprio come abbiamo fatto in precedenza con app.yaml, aggiungi l'utilizzo delle librerie grpcio e setuptools. Modifica appengine_config.py per supportare le librerie di terze parti integrate. Se ti sembra familiare, è perché era necessario anche nel modulo 2 durante la migrazione da App Engine ndb a Cloud NDB. La modifica esatta richiesta consiste nell'aggiungere la cartella lib al working set setuptools.pkg_resources:

4140b3800694f77e.png

*Differenze di Python 3

Questa sezione è facoltativa e solo se esegui il porting a Python 3. Una delle modifiche di benvenuto di App Engine di seconda generazione è che la copia (a volte chiamata "vendoring") di pacchetti di terze parti (non integrati) e il riferimento a pacchetti di terze parti integrati in app.yaml non sono più necessari, il che significa che puoi eliminare l'intero file appengine_config.py.

6. Aggiorna i file dell'applicazione

Esiste un solo file dell'applicazione, main.py, quindi tutte le modifiche in questa sezione interessano solo questo file. Abbiamo fornito una rappresentazione illustrata delle modifiche che apporteremo per eseguire la migrazione di questa applicazione a Cloud Memorystore. È solo a scopo illustrativo e non è pensato per essere analizzato nel dettaglio. Tutto il lavoro è nelle modifiche che apportiamo al codice.

5d043768ba7be742.png

Affrontiamo queste sezioni una alla volta, partendo dall'alto.

Aggiorna importazioni

La sezione di importazione in main.py per il modulo 12 utilizza Cloud NDB e Cloud Tasks. Ecco le relative importazioni:

PRIMA:

from flask import Flask, render_template, request
from google.appengine.api import memcache
from google.appengine.ext import ndb

Il passaggio a Memorystore richiede la lettura delle variabili di ambiente, il che significa che abbiamo bisogno del modulo Python os e di redis, il client Python Redis. Poiché Redis non può memorizzare nella cache gli oggetti Python, esegui il marshalling dell'elenco delle visite più recenti utilizzando pickle, quindi importalo. Un vantaggio di Memcache è che la serializzazione degli oggetti avviene automaticamente, mentre Memorystore è un po' più "fai da te". Infine, esegui l'upgrade da App Engine ndb a Cloud NDB sostituendo google.appengine.ext.ndb con google.cloud.ndb. Dopo queste modifiche, le importazioni dovrebbero avere il seguente aspetto:

DOPO:

import os
import pickle
from flask import Flask, render_template, request
from google.cloud import ndb
import redis

Aggiornamento inizializzazione

L'inizializzazione del modulo 12 consiste nell'istanziamento dell'oggetto applicazione Flask app e nell'impostazione di una costante per un'ora di memorizzazione nella cache:

PRIMA:

app = Flask(__name__)
HOUR = 3600

L'utilizzo delle API Cloud richiede un client, quindi crea un'istanza di un client Cloud NDB subito dopo Flask. Successivamente, recupera l'indirizzo IP e il numero di porta dell'istanza Memorystore dalle variabili di ambiente impostate in app.yaml. Con queste informazioni, crea un'istanza di un client Redis. Ecco come appare il codice dopo questi aggiornamenti:

DOPO:

app = Flask(__name__)
ds_client = ndb.Client()
HOUR = 3600
REDIS_HOST = os.environ.get('REDIS_HOST', 'localhost')
REDIS_PORT = os.environ.get('REDIS_PORT', '6379')
REDIS = redis.Redis(host=REDIS_HOST, port=REDIS_PORT)

*Migrazione a Python 3

Questa sezione è facoltativa se inizi dalla versione Python 3 dell'app del modulo 12. In questo caso, sono necessarie diverse modifiche relative a importazioni e inizializzazione.

Innanzitutto, poiché Memcache è un servizio in bundle di App Engine, il suo utilizzo in un'app Python 3 richiede l'SDK App Engine, in particolare il wrapping dell'applicazione WSGI (nonché altre configurazioni necessarie):

PRIMA:

from flask import Flask, render_template, request
from google.appengine.api import memcache, wrap_wsgi_app
from google.appengine.ext import ndb

app = Flask(__name__)
app.wsgi_app = wrap_wsgi_app(app.wsgi_app)
HOUR = 3600

Poiché stiamo eseguendo la migrazione a Cloud Memorystore (non un servizio integrato di App Engine come Memcache), l'utilizzo dell'SDK deve essere rimosso. È semplice, basta eliminare l'intera riga che importa sia memcache che wrap_wsgi_app. Elimina anche la riga che chiama wrap_wsgi_app(). Questi aggiornamenti lasciano questa parte dell'app (in realtà, l'intera app) identica alla versione Python 2.

DOPO:

import os
import pickle
from flask import Flask, render_template, request
from google.cloud import ndb
import redis

app = Flask(__name__)
ds_client = ndb.Client()
HOUR = 3600
REDIS_HOST = os.environ.get('REDIS_HOST', 'localhost')
REDIS_PORT = os.environ.get('REDIS_PORT', '6379')
REDIS = redis.Redis(host=REDIS_HOST, port=REDIS_PORT)

Infine, rimuovi l'utilizzo dell'SDK da app.yaml (elimina la riga: app_engine_apis: true) e requirements.txt (elimina la riga: appengine-python-standard).

Migrazione a Cloud Memorystore (e Cloud NDB)

Il modello dei dati di Cloud NDB è progettato per essere compatibile con ndb di App Engine, il che significa che la definizione degli oggetti Visit rimane invariata. Come nella migrazione del modulo 2 a Cloud NDB, tutte le chiamate Datastore in store_visit() e fetch_visits() vengono aumentate e incorporate in un nuovo blocco with (poiché è necessario l'utilizzo del gestore di contesto Cloud NDB). Ecco le chiamate prima di questa modifica:

PRIMA:

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 Visit.query().order(-Visit.timestamp).fetch(limit)

Aggiungi un blocco with ds_client.context() a entrambe le funzioni e inserisci le chiamate Datastore all'interno (con rientro). In questo caso, non sono necessarie modifiche alle chiamate:

DOPO:

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 Visit.query().order(-Visit.timestamp).fetch(limit)

Successivamente, esaminiamo le modifiche alla memorizzazione nella cache. Ecco la funzione main() del modulo 12:

PRIMA:

@app.route('/')
def root():
    'main application (GET) handler'
    # check for (hour-)cached visits
    ip_addr, usr_agt = request.remote_addr, request.user_agent
    visitor = '{}: {}'.format(ip_addr, usr_agt)
    visits = memcache.get('visits')

    # register visit & run DB query if cache empty or new visitor
    if not visits or visits[0].visitor != visitor:
        store_visit(ip_addr, usr_agt)
        visits = list(fetch_visits(10))
        memcache.set('visits', visits, HOUR)  # set() not add()

    return render_template('index.html', visits=visits)

Redis ha chiamate "get" e "set", proprio come Memcache. Tutto ciò che facciamo è scambiare le rispettive librerie client, giusto? Quasi. Come accennato in precedenza, non possiamo memorizzare nella cache un elenco Python con Redis (perché deve essere prima serializzato, cosa che Memcache fa automaticamente), quindi nella chiamata set(), "pickle" le visite in una stringa con pickle.dumps(). Allo stesso modo, quando recuperi le visite dalla cache, devi decomprimere il file con pickle.loads() subito dopo get(). Ecco l'handler principale dopo l'implementazione di queste modifiche:

DOPO:

@app.route('/')
def root():
    'main application (GET) handler'
    # check for (hour-)cached visits
    ip_addr, usr_agt = request.remote_addr, request.user_agent
    visitor = '{}: {}'.format(ip_addr, usr_agt)
    rsp = REDIS.get('visits')
    visits = pickle.loads(rsp) if rsp else None

    # register visit & run DB query if cache empty or new visitor
    if not visits or visits[0].visitor != visitor:
        store_visit(ip_addr, usr_agt)
        visits = list(fetch_visits(10))
        REDIS.set('visits', pickle.dumps(visits), ex=HOUR)

    return render_template('index.html', visits=visits)

Con questo si concludono le modifiche necessarie in main.py per convertire l'utilizzo di Memcache nell'app di esempio in Cloud Memorystore. Che ne dici del modello HTML e del porting a Python 3?

Aggiornare il file modello HTML e portarlo a Python 3?

Sorpresa! Non devi fare nulla, perché l'applicazione è stata progettata per essere eseguita sia su Python 2 sia su Python 3 senza modifiche al codice né librerie di compatibilità. Troverai main.py. identici nelle cartelle "FINISH" di mod13a (2.x) e mod13b (3.x). Lo stesso vale per requirements.txt , a parte eventuali differenze nei numeri di versione (se utilizzati). Poiché l'interfaccia utente rimane invariata, non sono previsti aggiornamenti neanche per templates/index.html.

Tutto il necessario per eseguire questa app su Python 3 App Engine è stato completato in precedenza nella configurazione: le direttive non necessarie sono state rimosse da app.yaml e sia appengine_config.py sia la cartella lib sono stati eliminati perché non vengono utilizzati in Python 3.

7. Riepilogo/Pulizia

Questa sezione conclude il codelab eseguendo il deployment dell'app, verificando che funzioni come previsto e in qualsiasi output riflesso. Dopo la convalida dell'app, esegui la pulizia e valuta i passaggi successivi.

Esegui il deployment e verifica l'applicazione

L'ultimo controllo consiste sempre nell'eseguire il deployment dell'app di esempio. Sviluppatori Python 2: elimina e reinstalla lib con i comandi riportati di seguito. Se sul sistema sono installati sia Python 2 che 3, potrebbe essere necessario eseguire esplicitamente pip2.

rm -rf ./lib
pip install -t lib -r requirements.txt

Ora gli sviluppatori di Python 2 e 3 devono eseguire il deployment delle loro app con:

gcloud app deploy

Poiché hai semplicemente modificato la struttura interna per un servizio di memorizzazione nella cache completamente diverso, l'app dovrebbe funzionare in modo identico all'app del modulo 12:

Modulo 7: app visitme

Questo passaggio completa il codelab. Ti invitiamo a confrontare l'app di esempio aggiornata con una delle cartelle del modulo 13, mod13a (Python 2) o mod13b (Python 3).

Esegui la pulizia

Generale

Se hai finito per il momento, ti consigliamo di disattivare l'app App Engine per evitare addebiti. Tuttavia, se vuoi fare altri test o esperimenti, la piattaforma App Engine ha una quota senza costi e, finché non superi questo livello di utilizzo, non ti verranno addebitati costi. Questo vale per il calcolo, ma potrebbero essere addebitati anche 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 "Specifiche per questo codelab" di seguito.

Per una divulgazione completa, il deployment su una piattaforma di calcolo serverless di Google Cloud come App Engine comporta costi di build e archiviazione minimi. Cloud Build ha una propria quota senza costi, così come Cloud Storage. L'archiviazione di questa immagine utilizza parte della quota. Tuttavia, potresti vivere in una regione che non dispone di un livello senza costi, quindi tieni sotto controllo l'utilizzo dello spazio di archiviazione per ridurre al minimo i potenziali costi. Le "cartelle" Cloud Storage specifiche che devi 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 di archiviazione riportati sopra dipendono dalla tua PROJECT_ID e dalla tua *LOC*, ad esempio "us" se la tua app è ospitata negli Stati Uniti.

D'altra parte, se non intendi continuare con questa applicazione o con altri codelab di migrazione correlati e vuoi eliminare tutto completamente, 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 ogni prodotto:

Questo tutorial ha comportato l'utilizzo di quattro prodotti Cloud:

  • App Engine
  • Cloud Datastore
  • Cloud Memorystore
  • Cloud VPC

Di seguito sono riportate le istruzioni per rilasciare queste risorse ed evitare/ridurre al minimo gli addebiti.

Arresta l'istanza Memorystore e il connettore VPC

Questi sono i prodotti senza un livello senza costi, quindi stai sostenendo costi di fatturazione in questo momento. Se non chiudi il progetto Cloud (vedi la sezione successiva), devi eliminare sia l'istanza Memorystore sia il connettore VPC per interrompere la fatturazione. Come quando hai creato queste risorse, puoi rilasciarle dalla console Cloud o dalla riga di comando.

Dalla console Cloud

Per eliminare l'istanza Memorystore, torna alla dashboard Memorystore e fai clic sull'ID istanza:

2b09baf1aa2e0a25.png

Una volta visualizzata la pagina dei dettagli dell'istanza, fai clic su "Elimina" e conferma:

f9d9eb1c1d4c6107.png

Per eliminare il connettore VPC, vai alla relativa dashboard, seleziona la casella di controllo accanto al connettore che vuoi eliminare, quindi fai clic su "Elimina" e conferma:

ca5fbd9f4c7c9b60.png

Dalla riga di comando

La seguente coppia di comandi gcloud elimina rispettivamente l'istanza Memorystore e il connettore VPC:

  • gcloud redis instances delete INSTANCE --region REGION
  • gcloud compute networks vpc-access connectors delete CONNECTOR --region REGION

Se non hai impostato l'ID progetto con gcloud config set project, potresti dover fornire --project PROJECT_ID. Se la tua istanza Memorystore si chiama demo-ms e il connettore VPC si chiama demo-vpc ed entrambi si trovano nella regione us-central1, esegui la seguente coppia di comandi e conferma:

$ gcloud redis instances delete demo-ms --region us-central1
You are about to delete instance [demo-ms] in [us-central1].
Any associated data will be lost.

Do you want to continue (Y/n)?

Delete request issued for: [demo-ms]
Waiting for operation [projects/PROJECT/locations/REGION/operations/operation-aaaaa-bbbbb-ccccc-ddddd] to complete...done.
Deleted instance [demo-ms].
$
$ gcloud compute networks vpc-access connectors delete demo-vpc --region us-central1
You are about to delete connector [demo-vpc] in [us-central1].
Any associated data will be lost.

Do you want to continue (Y/n)?

Delete request issued for: [demo-vpc]
Waiting for operation [projects/PROJECT/locations/REGION/operations/aaaaa-bbbb-cccc-dddd-eeeee] to complete...done.
Deleted connector [demo-vpc].

L'esecuzione di ogni richiesta richiede alcuni minuti. Questi passaggi sono facoltativi se scegli di chiudere l'intero progetto Cloud come descritto in precedenza, ma continuerai a ricevere fatture finché il processo di chiusura non sarà completato.

Passaggi successivi

Oltre a questo tutorial, altri moduli di migrazione che si concentrano sul passaggio dai servizi in bundle legacy da prendere in considerazione includono:

  • Modulo 2: esegui la migrazione da App Engine ndb a Cloud NDB
  • Moduli 7-9: esegui la migrazione delle attività push di App Engine Task Queue a Cloud Tasks
  • Moduli 12-13: esegui la migrazione da Memcache App Engine a Cloud Memorystore
  • Moduli 15-16: esegui la migrazione da App Engine Blobstore a Cloud Storage
  • Moduli 18-19: esegui la migrazione dalla coda di attività App Engine (attività pull) a Cloud Pub/Sub

App Engine non è più l'unica piattaforma serverless in Google Cloud. Se hai una piccola app App Engine o una con funzionalità limitate e vuoi trasformarla in un microservizio autonomo oppure 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 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 inserire la tua app in un container con Docker o il modulo 5 per farlo senza container, conoscenze di Docker o Dockerfiles

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 modifiche.

Indipendentemente dal modulo di migrazione che prenderai in considerazione, tutti i contenuti di Serverless Migration Station (codelab, video, codice sorgente [se disponibile]) sono accessibili nel relativo repository open source. Il repository README fornisce anche indicazioni sulle migrazioni da prendere in considerazione e sull'eventuale "ordine" dei moduli di migrazione pertinenti.

8. Risorse aggiuntive

Di seguito sono elencate risorse aggiuntive per gli sviluppatori che vogliono esplorare ulteriormente questo modulo di migrazione o quelli correlati, nonché i prodotti correlati. Sono inclusi i luoghi in cui fornire feedback su questi contenuti, i link al codice e vari documenti che potresti trovare utili.

Problemi/feedback relativi a Codelab

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 12 (INIZIO) e il modulo 13 (FINE) sono riportati nella tabella di seguito. 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 12

code

code

Modulo 13 (questo codelab)

code

code

Riferimenti online

Di seguito sono riportate risorse online che potrebbero essere pertinenti per questo tutorial:

App Engine

App Engine NDB e Cloud NDB

Memcache App Engine e Cloud Memorystore

Cloud VPC

Altre informazioni sul cloud

Licenza

Questo lavoro è concesso in licenza ai sensi di una licenza Creative Commons Attribution 2.0 Generic.