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

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.

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). È prevista anche una migrazione implicita da App Engine ndb a Cloud NDB, ma è trattata principalmente nel codelab del Modulo 2; dai un'occhiata per maggiori informazioni dettagliate.

Imparerai a utilizzare

  • Configurare un'istanza Cloud Memorystore (dalla console Cloud o dallo strumento gcloud)
  • Configura un connettore di accesso VPC Cloud serverless (dalla console Cloud 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
  • Esegui la migrazione da App Engine ndb a Cloud NDB

Che cosa ti serve

Sondaggio

Come utilizzerai questo tutorial?

Da leggere solo Leggilo e completa gli esercizi

Come valuteresti la tua esperienza con Python?

Principiante Livello intermedio Eccellente

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

Principiante Livello intermedio Eccellente

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). Questo processo comporta la sostituzione delle dipendenze nei servizi in bundle di App Engine, rendendo le tue app più portabili. Puoi scegliere di rimanere su App Engine o valutare di passare a una qualsiasi 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 su cloud completamente gestito. Memorystore supporta una coppia di motori di memorizzazione nella cache open source molto diffusi, Redis e Memcached. Questo modulo di migrazione utilizza Cloud Memorystore for Redis Per saperne di più, consulta la panoramica su Memorystore e Redis.

Poiché Memorystore richiede un server in esecuzione, è necessario anche Cloud VPC. In particolare, è necessario creare un connettore di accesso VPC serverless affinché l'app App Engine possa connettersi all'istanza Memorystore tramite il suo indirizzo IP privato. Una volta completato l'esercizio, avrai aggiornato l'app in modo che, mentre si comporta come prima, Cloud Memorystore sarà 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, seguita da un upgrade secondario aggiuntivo facoltativo a Python 3. Se hai già dimestichezza 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. Questa operazione comporterà la rimozione dell'uso dell'SDK poiché Memorystore non è un servizio in bundle di App Engine. L'apprendimento su come utilizzare l'SDK App Engine per Python 3 non rientra nell'ambito di questo tutorial.

Questo tutorial presenta i seguenti passaggi chiave:

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

3. Configurazione/prelavorazione

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 riutilizzare un altro progetto esistente. Ogni codelab di questa serie ha un "START" (il codice di base da cui iniziare) e "FINISH" (l'app di cui è stata eseguita la migrazione). Viene fornito il codice FINISH, per consentirti di confrontare le tue soluzioni con le nostre in caso di problemi. Puoi sempre tornare indietro per AVVIARE da capo se qualcosa va storto. Questi checkpoint sono progettati per garantire che tu possa imparare correttamente come eseguire le migrazioni.

Qualunque progetto Cloud utilizzi, assicurati che abbia un account di fatturazione attivo. Assicurati inoltre che App Engine sia abilitato. Esamina e assicurati di comprendere le implicazioni generali sui costi derivanti da questi tutorial. Tuttavia, a differenza degli altri di questa serie, questo codelab utilizza risorse Cloud che non hanno un livello senza costi, quindi saranno previsti dei costi per completare l'esercizio. Verranno fornite informazioni più specifiche sui costi insieme a suggerimenti per un utilizzo ridotto, incluse istruzioni alla fine sul rilascio delle risorse per ridurre al minimo gli addebiti.

Ottieni app di esempio di riferimento

Dal codice di base del Modulo 12 da cui iniziamo, questo codelab ti guiderà passo passo nella migrazione. Al termine, visualizzerai un'app del modulo 13 funzionante, molto simile al codice contenuto in una delle cartelle FINISH. Ecco le risorse:

La cartella START dovrebbe contenere i seguenti file:

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

Se inizi dalla versione Python 2, ci saranno anche un file appengine_config.py e possibilmente una cartella lib se hai completato il codelab del Modulo 12.

(Ri)Esegui il deployment dell'app Modulo 12

Passaggi preliminari rimanenti:

  1. Acquisisci familiarità con lo strumento a riga di comando gcloud (se necessario).
  2. (Ri)eseguire 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 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 l'aspetto e il funzionamento dell'app nel modulo 12, un'app web che monitora le visite, memorizzandole nella cache per lo stesso utente per un'ora:

dfe56a02ae59ddd8.png

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

4. Configura servizi di memorizzazione nella cache

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

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

Durante la creazione di tutte le risorse richieste, ripetiamo questi consigli per ridurre i costi. Inoltre, quando crei risorse Memorystore e VPC nella console Cloud, vedrai il Calcolatore prezzi per ciascun prodotto nell'angolo in alto a destra, con una stima dei costi mensili (vedi l'illustrazione di seguito). Questi valori vengono modificati automaticamente se modifichi le opzioni. Ecco più o meno ciò che dovresti aspettarti di vedere:

7eb35ebf7248c010.png

Entrambe le risorse sono obbligatorie e non importa quale crei per prima. Se crei prima l'istanza Memorystore, l'app App Engine non può raggiungerla senza il connettore VPC. Allo stesso modo, se crei prima il connettore VPC, non c'è nulla sulla rete VPC con cui l'app App Engine può comunicare. Questo tutorial illustra come creare l'istanza Memorystore, seguita dal connettore VPC.

Quando entrambe le risorse saranno online, aggiungerai le informazioni pertinenti a app.yaml per consentire alla tua app di accedere alla cache. Puoi anche fare riferimento alle guide di Python 2 o Python 3 nella documentazione ufficiale. Vale anche la guida sulla memorizzazione nella cache dei dati nella pagina di migrazione di Cloud NDB ( Python 2 o Python 3)

crea un'istanza Cloud Memorystore

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

  • Seleziona il livello di servizio più basso: Di base (valore predefinito della console: "Standard", valore predefinito di gcloud: "Di base").
  • Scegli la quantità minima di spazio di archiviazione: 1 GB (valore predefinito della console: 16 GB, impostazione predefinita di gcloud: 1 GB).
  • In genere le versioni più recenti di qualsiasi software richiedono la maggior quantità di risorse, ma probabilmente non è consigliato selezionare la versione meno recente. La seconda versione più recente al momento è la versione Redis 5.0 (valore predefinito della console: 6.x)

Tenendo presenti 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 in Cloud Console (ti potrebbero essere richiesti i dati di fatturazione). Se non hai ancora abilitato Memorystore, ti verrà chiesto di farlo:

68318997e3105db6.png

Dopo l'abilitazione (e possibilmente insieme alla fatturazione), si aprirà la dashboard Memorystore. Qui puoi vedere tutte le istanze create nel tuo progetto. Il progetto mostrato di seguito non ne ha nessuna, per questo motivo viene visualizzato il messaggio "Nessuna riga da visualizzare". Per creare un'istanza Memorystore, fai clic su Crea istanza in alto:

63547aa575838a36.png

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

b77d927287fdf4c7.png

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

Dalla riga di comando

Creare istanze Memorystore dalla console Cloud è visivamente informativo, alcuni preferiscono la riga di comando. Assicurati di aver installato e iniziato gcloud prima di procedere.

Come per la console Cloud, è necessario abilitare Cloud Memorystore for Redis. Esegui il comando gcloud services enable redis.googleapis.com e attendi che venga completato, 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 abilitato, l'esecuzione del comando (di nuovo) non ha effetti collaterali (negativi). Con il servizio abilitato, creiamo un'istanza Memorystore. Il comando ha il seguente aspetto:

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 insieme a un ID progetto di "my-project". La regione di questa app di esempio è us-central1 (uguale a 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 Redis che preferisci, ma stiamo usando la versione 5, come consigliata in precedenza. Date queste impostazioni, questo è il comando da emettere (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 di Cloud Console, gcloud utilizza risorse minime per impostazione predefinita. Il risultato è che né il livello di servizio né la quantità di spazio di archiviazione sono richiesti in quel comando. La creazione di un'istanza Memorystore richiede diversi minuti e al termine dell'operazione, prendi nota dell'indirizzo IP e del numero di porta dell'istanza poiché presto verranno aggiunti a app.yaml.

Conferma istanza creata

Dalla console Cloud o dalla riga di comando

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

Ecco il comando per verificare 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 vengono richieste le informazioni sull'istanza o per configurare l'app, assicurati di utilizzare HOST e PORT (non RESERVED_IP). La dashboard di Cloud Memorystore nella console Cloud ora dovrebbe visualizzare l'istanza:

c5a6948ec1c056ed.png

Dalla macchina virtuale Compute Engine

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

Crea un connettore di accesso VPC serverless

Come con Cloud Memorystore, puoi creare il connettore Cloud VPC serverless nella console Cloud o dalla riga di comando. Analogamente, Cloud VPC non ha un livello senza costi, quindi consigliamo di allocare la quantità minima di risorse per completare il codelab al fine di contenere i costi al minimo, e questo può essere ottenuto con queste impostazioni:

  • Seleziona il numero massimo più basso di istanze: 3 (console e valore predefinito di gcloud: 10)
  • Scegli il tipo di macchina con il costo più basso: f1-micro (valore predefinito della console: e2-micro, nessun valore predefinito di gcloud)

La sezione successiva illustra come creare il connettore dalla console Cloud utilizzando le impostazioni VPC Cloud sopra riportate. Se preferisci farlo dalla riga di comando, passa alla sezione successiva.

Dalla console Cloud

Vai a "Accesso VPC serverless" di Cloud Networking di Cloud Console (ti potrebbero essere richiesti i dati di fatturazione). Se non hai ancora abilitato l'API, ti verrà richiesto di farlo:

e3b9c0651de25e97.png

Una volta abilitata l'API (e, possibilmente insieme alla fatturazione), verrà visualizzata la dashboard in cui sono visualizzati tutti i connettori VPC creati. Il progetto utilizzato nello screenshot seguente non ne ha nessuna, per questo motivo è 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

Scegliere le impostazioni appropriate per le tue applicazioni. Per questo tutorial e la relativa app di esempio con esigenze minime, ha senso ridurre al minimo i costi, quindi segui i consigli trattati in precedenza. Dopo aver effettuato le selezioni, fai clic su Crea. La richiesta di un connettore VPC richiederà 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 inviato il seguente comando:

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

Quando 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 l'indirizzo IP iniziale di un blocco CIDR /28 inutilizzato. Questo tutorial parte dalle seguenti ipotesi:

  • ID progetto: my-project
  • Nome connettore VPC: demo-vpc
  • Numero minimo di istanze: 2 (impostazione predefinita) e numero massimo di istanze: 3
  • Tipo di istanza: f1-micro
  • Regione: us-central1
  • Blocco CIDR IPv4: 10.8.0.0/28 (come consigliato nella console Cloud)

Aspettati un output simile a quello che vedi qui sotto se esegui il comando seguente tenendo a mente i presupposti sopra:

$ 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 di valori predefiniti, ad esempio il numero minimo di istanze pari a 2 e una rete denominata default. La creazione di un connettore VPC richiede diversi minuti.

Conferma connettore creato

Una volta completato il processo, esegui questo comando gcloud (supponendo che si tratti della regione us-central1) per confermare che è 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

Allo stesso modo, ora dovrebbe essere visualizzato il connettore appena creato nella dashboard:

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 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, di solito vengono fornite ulteriori informazioni sull'ulteriore portabilità a Python 3 dei contenuti.

requirements.txt

In questa sezione stiamo aggiungendo pacchetti per supportare Cloud Memorystore e Cloud NDB. Per Cloud Memorystore for Redis è sufficiente utilizzare il client Redis standard per Python (redis), in quanto non esiste una libreria client Cloud Memorystore di base. Aggiungi sia redis che google-cloud-ndb a requirements.txt, entrando a far parte di flask dal modulo 12:

flask
redis
google-cloud-ndb

Questo file requirements.txt non presenta numeri di versione, il che significa che sono selezionate le versioni più recenti. In caso di incompatibilità, specifica i numeri di versione da bloccare nelle versioni funzionanti.

app.yaml

Nuove sezioni da aggiungere

Il runtime Python 2 di App Engine richiede pacchetti specifici di terze parti quando si utilizzano API Cloud come Cloud NDB, vale a dire 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 indicato di seguito:

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

Durante la migrazione della tua app, potrebbe già essere presente una sezione libraries. In caso affermativo, e mancano grpcio e setuptools, aggiungili alla sezione libraries esistente.

Successivamente, l'app di esempio richiede le informazioni sull'istanza Cloud Memorystore e sul connettore VPC, quindi aggiungi le due nuove sezioni seguenti a app.yaml, indipendentemente dal runtime Python in uso:

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

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

Questo è tutto per quanto riguarda gli aggiornamenti richiesti. Il tuo app.yaml aggiornato ora dovrebbe avere il seguente aspetto:

runtime: python27
threadsafe: yes
api_version: 1

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

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

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 un "prima e dopo" che illustra gli aggiornamenti da applicare a app.yaml:

ec2bb027a67debb6.png

*Le differenze in Python 3

Questa sezione è facoltativa e solo se esegui la portabilità in Python 3. Per farlo, ci sono una serie di modifiche da apportare alla configurazione di Python 2. Salta questa sezione se non stai eseguendo l'upgrade in questo momento.

Non vengono utilizzati né threadsafeapi_version per il runtime di Python 3, quindi elimina entrambe le impostazioni. Il runtime più recente di App Engine non supporta le librerie integrate di terze parti né la copia di librerie non integrate. L'unico requisito per i pacchetti di terze parti è elencarli in requirements.txt. Di conseguenza, è possibile eliminare l'intera sezione libraries di app.yaml.

In seguito, il runtime Python 3 richiede l'uso di framework web che eseguono il proprio routing, ecco perché abbiamo mostrato agli sviluppatori come eseguire la migrazione da webp2 a Flask nel modulo 1. Di conseguenza, tutti i gestori di script devono essere impostati su auto. Questa app non pubblica file statici, perciò è "inutile" in modo che vengano elencati i gestori (poiché sono tutti auto), quindi è possibile rimuovere anche l'intera sezione handlers. Di conseguenza, il tuo nuovo app.yaml abbreviato ottimizzato per Python 3 deve 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

Riassumendo le differenze di app.yaml durante la portabilità in Python 3:

  • Elimina le impostazioni di threadsafe e api_version
  • Elimina 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 durante la creazione delle risorse in precedenza. Per quanto riguarda l'istanza Memorystore, assicurati di utilizzare HOST (non RESERVED_IP) e PORT. Ecco un modo rapido dalla riga di comando per ottenere HOST e PORT supponendo che il nome di istanza sia demo-ms e 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 dell'istanza Redis di esempio era 10.10.10.10 utilizzando la porta 6379 nel nostro progetto my-project che si trova nella regione us-central1 con il nome del connettore VPC di demo-vpc, queste sezioni in app.yaml saranno simili alla seguente:

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

Aggiungi il supporto per le librerie di terze parti integrate

Proprio come con app.yaml in precedenza, 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 richiesto anche nel Modulo 2 durante la migrazione da App Engine ndb a Cloud NDB. La modifica esatta necessaria consiste nell'aggiungere la cartella lib al set di lavoro setuptools.pkg_resources:

4140b3800694f77e.png

*Le differenze in Python 3

Questa sezione è facoltativa e solo se esegui la portabilità in Python 3. Una delle modifiche apprezzate di seconda generazione di App Engine è che non è più necessario copiare (a volte "vendoring") di pacchetti di terze parti (non integrati) e fare riferimento a pacchetti di terze parti integrati in app.yaml, 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 quel file. Abbiamo fornito una rappresentazione grafica delle modifiche che apporteremo per migrare questa applicazione a Cloud Memorystore. Ha scopo puramente illustrativo e non è destinata a un'analisi approfondita. Tutto il lavoro consiste nelle modifiche che apportiamo al codice.

5d043768ba7be742.png

Vediamo una sezione 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 loro 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 os Python e di redis, il client Python di Redis. Poiché Redis non può memorizzare nella cache gli oggetti Python, esegui il marshall dell'elenco delle visite più recenti utilizzando pickle, quindi importa anche quello. 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

Aggiorna inizializzazione

L'inizializzazione del modulo 12 consiste nel creare un'istanza dell'oggetto applicazione Flask app e nell'impostare 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 per un client Cloud NDB subito dopo Flask. Successivamente, recupera l'indirizzo IP e il numero di porta per l'istanza Memorystore dalle variabili di ambiente impostate in app.yaml. Grazie a queste informazioni, crea un'istanza per un client Redis. Ecco come si presenta 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 di Python 3

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

In primo luogo, poiché Memcache è un servizio in bundle di App Engine, il suo utilizzo in un'app Python 3 richiede l'SDK di App Engine, che include l'applicazione WSGI (nonché altra configurazione necessaria):

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 in bundle con App Engine come Memcache), è necessario rimuovere l'utilizzo dell'SDK. Questa operazione è semplice perché dovrai semplicemente eliminare l'intera riga che importa sia memcache sia wrap_wsgi_app. Elimina anche la linea 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).

Esegui la migrazione a Cloud Memorystore (e Cloud NDB)

Il modello dei dati di Cloud NDB è pensato per essere compatibile con i ndb di App Engine, il che significa che la definizione degli oggetti Visit rimane la stessa. Simulando la migrazione del Modulo 2 a Cloud NDB, tutte le chiamate Datastore in store_visit() e fetch_visits() sono aumentate e incorporate in un nuovo blocco with (poiché è richiesto l'uso del gestore di contesto Cloud NDB). Queste sono le chiamate precedenti a 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 (e rientrate). In questo caso, non sono necessarie modifiche alle chiamate stesse:

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)

Vediamo ora 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 "get" e "set" come memcache. Non dobbiamo solo scambiare le rispettive librerie client, giusto? Ci sei quasi. Come accennato in precedenza, non possiamo memorizzare nella cache un elenco Python con Redis (perché deve essere prima serializzato, cosa che gestisce automaticamente memcache), quindi nella chiamata set(), "pickle" le visite in una stringa con pickle.dumps(). Allo stesso modo, quando recuperi visite dalla cache, devi deselezionarlo con pickle.loads() subito dopo get(). Ecco il gestore principale dopo aver implementato 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)

Si conclude qui le modifiche richieste in main.py che convertono l'utilizzo di Memcache nell'app di esempio in Cloud Memorystore. E il modello HTML e la portabilità in Python 3?

Aggiornare il file e la porta del modello HTML in Python 3?

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

Tutto il necessario per eseguire questa app nell'App Engine Python 3 è stato completato in precedenza nella configurazione: le istruzioni non necessarie sono state rimosse da app.yaml e sia appengine_config.py sia la cartella lib sono state eliminate perché non erano utilizzate in Python 3.

7. 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 la pulizia e valuta i passaggi successivi.

Esegui il deployment e verifica l'applicazione

L'ultimo controllo riguarda sempre il deployment dell'app di esempio. Sviluppatori Python 2: elimina e reinstalla lib utilizzando i comandi seguenti. (Se sul sistema sono installati entrambi, Python 2 e 3, potrebbe essere necessario eseguire in modo esplicito pip2.)

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

Entrambi gli sviluppatori Python 2 e 3 dovrebbero ora eseguire il deployment delle loro app con:

gcloud app deploy

Poiché hai semplicemente ricostruito le cose dietro le quinte per un servizio di memorizzazione nella cache completamente diverso, l'app stessa dovrebbe funzionare in modo identico all'app del modulo 12:

Modulo 7 - App Visitami

Questo passaggio completa il codelab. Ti invitiamo a confrontare la tua app di esempio aggiornata con una delle cartelle del Modulo 13, mod13a (Python 2) o mod13b (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:

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

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

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

Arresto dell'istanza Memorystore e del connettore VPC

Questi sono i prodotti senza un livello senza costi, quindi ti sono addebitati dei costi al momento. Se non arresti il progetto Cloud (vedi la sezione successiva), devi eliminare sia l'istanza Memorystore sia il connettore VPC per interrompere la fatturazione. Analogamente a quando hai creato queste risorse, puoi anche rilasciarle dalla console Cloud o dalla riga di comando.

Dalla console Cloud

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

2b09baf1aa2e0a25.png

Nella pagina dei dettagli dell'istanza, fai clic su "Elimina". e conferma:

f9d9eb1c1d4c6107.png

Per eliminare il connettore VPC, vai alla sua dashboard e seleziona la casella di controllo accanto al connettore da 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 l'istanza Memorystore si chiama demo-ms e il connettore VPC denominato demo-vpc ed entrambi si trovano nella regione us-central1, invia 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 arrestare l'intero progetto Cloud come descritto in precedenza, ma riceverai comunque addebiti fino al completamento del processo di arresto.

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 15-16: migrazione dal Blobstore di App Engine a Cloud Storage
  • 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.

8. Risorse aggiuntive

Di seguito sono elencate le risorse aggiuntive per gli sviluppatori che esplorano ulteriormente questo modulo di migrazione o i prodotti correlati, nonché i prodotti correlati. tra cui posizioni in cui fornire feedback su questi contenuti, link al codice e vari documenti che potrebbero esserti utili.

Problemi/feedback dei 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 12 (START) e il modulo 13 (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 12

codice

codice

Modulo 13 (questo codelab)

codice

codice

Riferimenti online

Di seguito sono riportate alcune risorse online che potrebbero essere pertinenti per questa esercitazione:

App Engine

NDB di App Engine e Cloud NDB

Memcache App Engine e Cloud Memorystore

VPC Cloud

Altre informazioni sul cloud

Licenza

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