1. Visão geral
A série de codelabs da Serverless Migration Station (tutoriais práticos e autoguiados) e os vídeos relacionados têm como objetivo ajudar os desenvolvedores sem servidor do Google Cloud a modernizar os aplicativos orientando-os em uma ou mais migrações, principalmente a migração de serviços legados. Isso torna seus apps mais portáteis e oferece mais opções e flexibilidade, permitindo que você se integre e acesse uma variedade maior de produtos do Cloud e faça upgrade mais fácil para versões de linguagem mais recentes. Embora o foco inicial seja nos primeiros usuários do Cloud, principalmente desenvolvedores do App Engine (ambiente padrão), esta série é ampla o suficiente para incluir outras plataformas sem servidor, como o Cloud Functions e o Cloud Run, ou em outro lugar, se aplicável.
O objetivo deste codelab é mostrar aos desenvolvedores do App Engine em Python 2 como migrar do Memcache do App Engine para o Cloud Memorystore (para Redis). Há também uma migração implícita do App Engine ndb para o Cloud NDB, mas isso é abordado principalmente no codelab do módulo 2. Confira para mais informações detalhadas.
Você vai aprender a
- Configure uma instância do Cloud Memorystore (no Console do Cloud ou na ferramenta
gcloud) - Configure um conector de acesso VPC sem servidor do Cloud (no Console do Cloud ou na ferramenta
gcloud) - Migrar do Memcache do App Engine para o Cloud Memorystore
- Implementar o armazenamento em cache com o Cloud Memorystore em um app de exemplo
- Migrar do App Engine
ndbpara o Cloud NDB
O que é necessário
- Um projeto do Google Cloud com uma conta de faturamento ativa (este não é um codelab sem custo financeiro)
- Habilidades básicas em Python
- Conhecimento prático de comandos comuns do Linux
- Conhecimento básico sobre desenvolvimento e implantação de apps do App Engine
- Um app do App Engine do Módulo 12 funcional. Conclua o codelab do Módulo 12 (recomendado) ou copie o app do Módulo 12 do repositório.
Pesquisa
Como você usará este tutorial?
Como você classificaria sua experiência com Python?
Como você classificaria sua experiência de uso dos serviços do Google Cloud?
2. Contexto
Este codelab demonstra como migrar um app de exemplo do Memcache do App Engine (e NDB) para o Cloud Memorystore (e Cloud NDB). Esse processo envolve a substituição de dependências nos serviços incluídos do App Engine, tornando seus apps mais portáteis. Você pode continuar usando o App Engine ou considerar a migração para qualquer uma das alternativas descritas anteriormente.
Essa migração exige mais esforço em comparação com as outras desta série. A substituição recomendada para o Memcache do App Engine é o Cloud Memorystore, um serviço de armazenamento em cache totalmente gerenciado e baseado na nuvem. O Memorystore é compatível com dois mecanismos de armazenamento em cache de código aberto conhecidos: Redis e Memcached. Este módulo de migração usa o Cloud Memorystore para Redis. Saiba mais na visão geral do Memorystore e do Redis.
Como o Memorystore exige um servidor em execução, também é necessário ter uma VPC do Cloud. Especificamente, um conector de acesso VPC sem servidor precisa ser criado para que o app do App Engine possa se conectar à instância do Memorystore usando o endereço IP particular dela. Ao concluir este exercício, você terá atualizado o app para que, embora ele se comporte como antes, o Cloud Memorystore seja o serviço de cache, substituindo o serviço Memcache do App Engine.
Este tutorial começa com o app de exemplo do Módulo 12 em Python 2, seguido por um upgrade adicional, opcional e secundário para o Python 3. Se você já sabe como acessar os serviços incluídos do App Engine no Python 3 usando o SDK do App Engine para Python 3, comece com a versão em Python 3 do app de exemplo do módulo 12. Isso vai exigir a remoção do uso do SDK, já que o Memorystore não é um serviço integrado do App Engine. Aprender a usar o SDK do App Engine para Python 3 está fora do escopo deste tutorial.
Este tutorial inclui as seguintes etapas principais:
- Configuração/pré-trabalho
- Configurar serviços de armazenamento em cache
- Atualizar os arquivos de configuração
- Atualizar aplicativo principal
3. Configuração/pré-trabalho
Preparar o projeto na nuvem
Recomendamos que você reutilize o mesmo projeto usado para concluir o codelab do Módulo 12. Se preferir, crie um novo projeto ou reutilize outro. Cada codelab desta série tem um "INÍCIO" (o código de base para começar) e um "FIM" (o app migrado). O código FINISH é fornecido para que você possa comparar suas soluções com as nossas em caso de problemas. Você sempre pode voltar ao INÍCIO se algo der errado. Esses pontos de verificação foram criados para garantir que você aprenda a realizar as migrações.
Qualquer projeto na nuvem que você usar precisa ter uma conta de faturamento ativa. Verifique também se o App Engine está ativado. Analise e entenda as implicações gerais de custo ao fazer estes tutoriais. Ao contrário de outros codelabs desta série, este usa recursos do Cloud que não têm um nível sem custo financeiro. Portanto, haverá alguns custos para concluir o exercício. Informações mais específicas sobre custos serão fornecidas com recomendações para reduzir o uso, incluindo instruções no final sobre como liberar recursos para minimizar as cobranças de faturamento.
Receber app de amostra do valor de referência
Com base no código do módulo 12, este codelab mostra a migração etapa por etapa. Quando concluído, você vai chegar a um app do Módulo 13 funcionando, muito parecido com o código em uma das pastas FINISH. Confira esses recursos:
- INICIAR: app Python 2 do módulo 12 (
mod12) ou Python 3 (mod12b) - CONCLUIR: app Python 2 do módulo 13 (
mod13a) ou Python 3 (mod13b) - Repositório de migração completo (clonar ou fazer o download do ZIP)
A pasta START deve conter os seguintes arquivos:
$ ls README.md app.yaml main.py requirements.txt templates
Se você estiver começando com a versão em Python 2, também haverá um arquivo appengine_config.py e possivelmente uma pasta lib se você tiver concluído o codelab do Módulo 12.
(Re)implantar o app do módulo 12
As etapas de pré-trabalho restantes:
- Familiarize-se com a ferramenta de linha de comando
gcloud(se necessário). - (Re)implante o código do módulo 12 no App Engine (se necessário)
Os usuários do Python 2 precisam excluir e reinstalar a pasta lib com estes comandos:
rm -rf ./lib; pip install -t lib -r requirements.txt
Agora, todos (usuários do Python 2 e 3) precisam fazer upload do código para o App Engine com este comando:
gcloud app deploy
Depois de implantado, confirme se o app tem a mesma aparência e funciona da mesma forma que o app do módulo 12, um web app que rastreia visitas, armazenando em cache para o mesmo usuário por uma hora:

Como as visitas mais recentes são armazenadas em cache, as atualizações de página devem ser carregadas com bastante rapidez.
4. Configurar serviços de armazenamento em cache
O Cloud Memorystore não é sem servidor. Uma instância é necessária. Neste caso, uma instância do Redis em execução. Ao contrário do Memcache, o Memorystore é um produto independente do Cloud e não tem um nível sem custo financeiro. Por isso, confira as informações de preços do Memorystore para Redis antes de continuar. Para minimizar os custos deste exercício, recomendamos a menor quantidade de recursos para operar: um nível de serviço Básico e uma capacidade de 1 GB.
A instância do Memorystore está em uma rede diferente do aplicativo do App Engine (instâncias). Por isso, é necessário criar um conector de acesso VPC sem servidor para que o App Engine possa acessar os recursos do Memorystore. Para minimizar os custos da VPC, escolha o tipo de instância (f1-micro) e o menor número de instâncias a serem solicitadas (sugerimos mínimo de 2 e máximo de 3). Confira também a página de informações sobre preços da VPC.
Repetimos essas recomendações para reduzir custos enquanto mostramos como criar cada recurso necessário. Além disso, ao criar recursos do Memorystore e da VPC no console do Cloud, você vai encontrar a calculadora de preços de cada produto no canto superior direito, com uma estimativa de custo mensal (veja a ilustração abaixo). Esses valores são ajustados automaticamente se você mudar as opções. É mais ou menos isso que você vai encontrar:

Os dois recursos são obrigatórios, e não importa qual você cria primeiro. Se você criar a instância do Memorystore primeiro, o app do App Engine não poderá acessá-la sem o conector de VPC. Da mesma forma, se você criar o conector de VPC primeiro, não haverá nada nessa rede VPC para o app do App Engine se comunicar. Neste tutorial, você vai criar primeiro a instância do Memorystore e depois o conector de VPC.
Depois que os dois recursos estiverem on-line, adicione as informações relevantes a app.yaml para que o app possa acessar o cache. Você também pode consultar os guias do Python 2 ou do Python 3 na documentação oficial. O guia de armazenamento em cache de dados na página de migração do Cloud NDB ( Python 2 ou Python 3) também é uma boa referência.
Criar uma instância do Cloud Memorystore
Como o Cloud Memorystore não tem um nível sem custo financeiro, recomendamos alocar a menor quantidade de recursos possível para concluir o codelab. Para manter os custos no mínimo, use estas configurações:
- Selecione o nível de serviço mais baixo: Básico (padrão do console: "Padrão", padrão do
gcloud: "Básico"). - Escolha a menor quantidade de armazenamento: 1 GB (padrão do console: 16 GB, padrão do
gcloud: 1 GB). - Normalmente, as versões mais recentes de qualquer software exigem a maior quantidade de recursos, mas selecionar a versão mais antiga também não é recomendado. A segunda versão mais recente é Redis versão 5.0 (padrão do console: 6.x)
Com essas configurações em mente, a próxima seção vai orientar você na criação da instância no console do Cloud. Se preferir fazer isso na linha de comando, pule para a frente.
No Console do Cloud
Acesse a página do Cloud Memorystore no console do Cloud. Talvez seja necessário informar dados de faturamento. Se você ainda não tiver ativado o Memorystore, será solicitado a fazer isso:

Depois de ativar (e talvez junto com o faturamento), você vai acessar o painel do Memorystore. É aqui que você pode conferir todas as instâncias criadas no seu projeto. O projeto mostrado abaixo não tem nenhuma, por isso aparece a mensagem "Nenhuma linha para mostrar". Para criar uma instância do Memorystore, clique em Criar instância na parte de cima:

Esta página tem um formulário para preencher com as configurações desejadas e criar a instância do Memorystore:

Para manter os custos baixos neste tutorial e no app de exemplo, siga as recomendações abordadas anteriormente. Depois de fazer as seleções, clique em Criar. O processo de criação leva vários minutos. Quando terminar, copie o endereço IP e o número da porta da instância para adicionar a app.yaml.
Na linha de comando
Embora seja visualmente informativo criar instâncias do Memorystore no Console do Cloud, algumas pessoas preferem a linha de comando. Verifique se o gcloud está instalado e inicializado antes de continuar.
Assim como no Console do Cloud, o Cloud Memorystore para Redis precisa estar ativado. Emita o comando gcloud services enable redis.googleapis.com e aguarde a conclusão, como neste exemplo:
$ gcloud services enable redis.googleapis.com Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.
Se o serviço já estiver ativado, executar o comando (de novo) não terá efeitos colaterais (negativos). Com o serviço ativado, vamos criar uma instância do Memorystore. O comando tem esta aparência:
gcloud redis instances create NAME --redis-version VERSION \
--region REGION --project PROJECT_ID
Escolha um nome para sua instância do Memorystore. Este laboratório usa "demo-ms" como nome e o ID do projeto "my-project". A região deste app de exemplo é us-central1 (igual a us-central), mas você pode usar uma mais próxima se a latência for um problema. Selecione a mesma região do seu app do App Engine. Você pode escolher qualquer versão do Redis, mas estamos usando a versão 5, conforme recomendado anteriormente. Com essas configurações, este é o comando que você vai emitir (junto com a saída associada):
$ 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].
Ao contrário dos padrões do console do Cloud, gcloud usa recursos mínimos por padrão. O resultado é que nem o nível de serviço nem a quantidade de armazenamento foram necessários nesse comando. A criação de uma instância do Memorystore leva alguns minutos. Quando ela estiver pronta, anote o endereço IP e o número da porta da instância, porque eles serão adicionados a app.yaml em breve.
Confirmar a criação da instância
No console do Cloud ou na linha de comando
Se você criou a instância no Console do Cloud ou na linha de comando, confirme se ela está disponível e pronta para uso com este comando: gcloud redis instances list --region REGION
Confira o comando para verificar instâncias na região us-central1 e a saída esperada mostrando a instância que acabamos de criar:
$ 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 for solicitado a informar os dados da instância ou configurar o app, use HOST e PORT (não RESERVED_IP). O painel do Cloud Memorystore no Console do Cloud agora vai mostrar essa instância:

De uma máquina virtual do Compute Engine
Se você tiver uma máquina virtual (VM) do Compute Engine, também poderá enviar comandos diretos da VM para a instância do Memorystore e confirmar se ela está funcionando. O uso de uma VM pode ter custos associados, independentemente dos recursos que você já está usando.
Criar um conector de acesso VPC sem servidor
Assim como no Cloud Memorystore, é possível criar o conector de VPC sem servidor do Cloud no Console do Cloud ou na linha de comando. Da mesma forma, a VPC do Cloud não tem um nível sem custo financeiro. Por isso, recomendamos alocar a menor quantidade de recursos para concluir o codelab e manter os custos no mínimo. Isso pode ser feito com estas configurações:
- Selecione o menor número máximo de instâncias: 3 (console e padrão do
gcloud: 10) - Escolha o tipo de máquina de menor custo:
f1-micro(padrão do console:e2-micro, sem padrãogcloud)
A próxima seção vai mostrar como criar o conector no console do Cloud usando as configurações de VPC do Cloud acima. Se você preferir fazer isso na linha de comando, avance para a próxima seção.
No Console do Cloud
Acesse a página Rede do Cloud "Acesso VPC sem servidor" no console do Cloud. Talvez seja necessário informar dados de faturamento. Se você ainda não tiver ativado a API, será solicitado a fazer isso:

Depois de ativar a API (e possivelmente o faturamento), você vai acessar o painel que mostra todos os conectores de VPC criados. O projeto usado na captura de tela abaixo não tem nenhuma, por isso a mensagem "Nenhuma linha para mostrar". No console, clique em Criar conector na parte de cima:

Preencha o formulário com as configurações desejadas:

Escolha as configurações adequadas para seus aplicativos. Para este tutorial e o app de exemplo com necessidades mínimas, faz sentido minimizar os custos. Portanto, siga as recomendações abordadas anteriormente. Depois de fazer as seleções, clique em Criar. A solicitação de um conector de VPC leva alguns minutos para ser concluída.
Pela linha de comando
Antes de criar um conector de VPC, ative a API de acesso VPC sem servidor. Você vai ver uma saída semelhante depois de executar o seguinte comando:
$ gcloud services enable vpcaccess.googleapis.com Operation "operations/acf.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.
Com a API ativada, um conector de VPC é criado com um comando semelhante a este:
gcloud compute networks vpc-access connectors create CONNECTOR_NAME \
--range 10.8.0.0/28 --region REGION --project PROJECT_ID
Escolha um nome para o conector e um endereço IP inicial de bloco CIDR /28 não utilizado. Este tutorial parte das seguintes premissas:
- Project ID:
my-project - Nome do conector de VPC:
demo-vpc - Instâncias mínimas: 2 (padrão) e instâncias máximas: 3
- Tipo de instância:
f1-micro - Região:
us-central1 - Bloco CIDR IPv4:
10.8.0.0/28(conforme recomendado no console do Google Cloud)
A saída será semelhante a esta se você executar o comando a seguir com as proposições acima:
$ 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].
O comando acima omite a especificação de valores padrão, como um mínimo de duas instâncias e uma rede chamada default. A criação de um conector de VPC leva vários minutos.
Confirmar se o conector foi criado
Quando o processo for concluído, execute o seguinte comando gcloud, supondo que seja a região us-central1, para confirmar que ele foi criado e está pronto para 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
Da mesma forma, o painel agora vai mostrar o conector que você acabou de criar:

Anote o ID do projeto na nuvem, o nome do conector de VPC e a região.
Agora que você criou os recursos adicionais do Cloud necessários, seja por linha de comando ou no console, é hora de atualizar a configuração do aplicativo para oferecer suporte ao uso deles.
5. Atualizar os arquivos de configuração
A primeira etapa é fazer todas as atualizações necessárias nos arquivos de configuração. Ajudar os usuários do Python 2 a migrar é o principal objetivo deste codelab. No entanto, esse conteúdo geralmente é seguido de informações sobre a portabilidade para o Python 3 em cada seção abaixo.
requirements.txt
Nesta seção, vamos adicionar pacotes para oferecer suporte ao Cloud Memorystore e ao Cloud NDB. Para o Cloud Memorystore para Redis, basta usar o cliente Redis padrão para Python (redis), já que não há uma biblioteca de cliente do Cloud Memorystore. Anexe redis e google-cloud-ndb a requirements.txt, unindo flask do Módulo 12:
flask
redis
google-cloud-ndb
Esse arquivo requirements.txt não tem números de versão, o que significa que as versões mais recentes estão selecionadas. Se houver incompatibilidades, especifique os números de versão para bloquear as versões em funcionamento.
app.yaml
Novas seções para adicionar
O ambiente de execução do Python 2 do App Engine exige pacotes específicos de terceiros ao usar APIs do Cloud, como o Cloud NDB, ou seja, grpcio e setuptools. Os usuários do Python 2 precisam listar bibliotecas integradas como essas junto com uma versão disponível em app.yaml. Se você ainda não tiver uma seção libraries, crie uma e adicione as duas bibliotecas da seguinte maneira:
libraries:
- name: grpcio
version: latest
- name: setuptools
version: latest
Ao migrar seu app, ele já pode ter uma seção libraries. Se houver e grpcio ou setuptools estiverem faltando, adicione-os à seção libraries.
Em seguida, nosso app de exemplo precisa das informações da instância do Cloud Memorystore e do conector de VPC. Por isso, adicione as duas novas seções a seguir a app.yaml, independente de qual ambiente de execução do Python você está usando:
env_variables:
REDIS_HOST: 'YOUR_REDIS_HOST'
REDIS_PORT: 'YOUR_REDIS_PORT'
vpc_access_connector:
name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR
Essas são as atualizações necessárias. Seu app.yaml atualizado vai ficar assim:
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
Confira abaixo um "antes e depois" ilustrando as atualizações que você precisa aplicar a app.yaml:

*Diferenças do Python 3
Esta seção é opcional e só é necessária se você estiver fazendo a portabilidade para o Python 3. Para isso, é necessário fazer várias mudanças na configuração do Python 2. Pule esta seção se você não estiver fazendo upgrade no momento.
Nem threadsafe nem api_version são usados no ambiente de execução do Python 3. Portanto, exclua essas duas configurações. O ambiente de execução mais recente do App Engine não é compatível com bibliotecas de terceiros integradas nem com a cópia de bibliotecas não integradas. O único requisito para pacotes de terceiros é listá-los em requirements.txt. Como resultado, toda a seção libraries de app.yaml pode ser excluída.
Em seguida, o ambiente de execução do Python 3 exige o uso de frameworks da Web que fazem o próprio roteamento. Por isso, mostramos aos desenvolvedores como migrar do webp2 para o Flask no módulo 1. Como resultado, todos os gerenciadores de script precisam ser alterados para auto. Como esse app não veicula arquivos estáticos, é "inútil" ter gerenciadores listados (já que todos são auto). Portanto, toda a seção handlers também pode ser removida. Como resultado, seu novo app.yaml abreviado e ajustado para Python 3 deve ser encurtado para ficar assim:
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
Resumindo as diferenças em app.yaml ao migrar para o Python 3:
- Excluir as configurações de
threadsafeeapi_version - Excluir a seção
libraries - Exclua a seção
handlers(ou apenas os gerenciadoresscriptse o app veicular arquivos estáticos)
Substitua os valores
Os valores nas novas seções do Memorystore e do conector de VPC são apenas marcadores de posição. Substitua esses valores em maiúsculas (YOUR_REDIS_HOST, YOUR_REDIS_PORT, PROJECT_ID, REGION, CONNECTOR_NAME) pelos valores salvos quando você criou esses recursos anteriormente. Em relação à instância do Memorystore, use HOST (não RESERVED_IP) e PORT. Confira uma maneira rápida de linha de comando para receber o HOST e o PORT, supondo um nome de instância demo-ms e que o REGION seja us-central1:
$ gcloud redis instances describe demo-ms --region us-central1 \
--format "value(host,port)"
10.251.161.51 6379
Se o endereço IP da nossa instância de exemplo do Redis fosse 10.10.10.10 usando a porta 6379 no projeto my-project localizado na região us-central1 com um nome de conector de VPC demo-vpc, estas seções em app.yaml seriam assim:
env_variables:
REDIS_HOST: '10.10.10.10'
REDIS_PORT: '6379'
vpc_access_connector:
name: projects/my-project/locations/us-central1/connectors/demo-vpc
Criar ou atualizar appengine_config.py
Adicionar suporte a bibliotecas integradas de terceiros
Assim como fizemos com app.yaml antes, adicione o uso das bibliotecas grpcio e setuptools. Modifique appengine_config.py para oferecer suporte a bibliotecas integradas de terceiros. Se isso parece familiar, é porque também era necessário no Módulo 2 ao migrar do App Engine ndb para o Cloud NDB. A mudança exata necessária é adicionar a pasta lib ao conjunto de trabalho setuptools.pkg_resources:

*Diferenças do Python 3
Esta seção é opcional e só é necessária se você estiver fazendo a portabilidade para o Python 3. Uma das mudanças bem-vindas da segunda geração do App Engine é que não é mais necessário copiar (às vezes chamado de "vendoring") pacotes de terceiros (não integrados) e referenciar pacotes de terceiros integrados em app.yaml. Isso significa que você pode excluir todo o arquivo appengine_config.py.
6. Atualizar arquivos do aplicativo
Há apenas um arquivo de aplicativo, main.py, então todas as mudanças nesta seção afetam apenas esse arquivo. Fornecemos uma representação ilustrada das mudanças que vamos fazer para migrar esse aplicativo para o Cloud Memorystore. Ele é apenas para fins ilustrativos e não deve ser analisado com atenção. Todo o trabalho está nas mudanças que fazemos no código.

Vamos abordar cada seção por vez, começando de cima para baixo.
Atualizar importações
A seção de importação em main.py do módulo 12 usa o Cloud NDB e o Cloud Tasks. Confira as importações:
ANTES:
from flask import Flask, render_template, request
from google.appengine.api import memcache
from google.appengine.ext import ndb
Para mudar para o Memorystore, é necessário ler variáveis de ambiente. Isso significa que precisamos do módulo os do Python e do redis, o cliente Redis do Python. Como o Redis não pode armazenar em cache objetos Python, faça o marshall da lista de visitas mais recentes usando pickle. Portanto, importe isso também. Um benefício do Memcache é que a serialização de objetos acontece automaticamente, enquanto o Memorystore é um pouco mais "faça você mesmo". Por fim, faça upgrade do App Engine ndb para o Cloud NDB substituindo google.appengine.ext.ndb por google.cloud.ndb. Depois de essas mudanças, as importações vão ficar assim:
AFTER:
import os
import pickle
from flask import Flask, render_template, request
from google.cloud import ndb
import redis
Atualizar inicialização
A inicialização do módulo 12 consiste em instanciar o objeto do aplicativo Flask app e definir uma constante para uma hora de armazenamento em cache:
ANTES:
app = Flask(__name__)
HOUR = 3600
O uso das APIs do Cloud exige um cliente. Portanto, crie uma instância de um cliente do Cloud NDB logo após o Flask. Em seguida, extraia o endereço IP e o número da porta da instância do Memorystore das variáveis de ambiente definidas em app.yaml. Com essas informações, crie uma instância de um cliente Redis. Veja como fica o código após essas atualizações:
AFTER:
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)
*Migração para o Python 3
Esta seção é opcional e se você estiver começando com a versão em Python 3 do app do módulo 12. Se for o caso, há várias mudanças necessárias relacionadas a importações e inicialização.
Primeiro, como o Memcache é um serviço incluído do App Engine, o uso dele em um app Python 3 exige o SDK do App Engine, especificamente o encapsulamento do aplicativo WSGI (além de outras configurações necessárias):
ANTES:
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
Como estamos migrando para o Cloud Memorystore (não um serviço incluído do App Engine, como o Memcache), o uso do SDK precisa ser removido. É simples, basta excluir toda a linha que importa memcache e wrap_wsgi_app. Exclua também a linha que chama wrap_wsgi_app(). Essas atualizações deixam essa parte do app (na verdade, o app inteiro) idêntica à versão do Python 2.
AFTER:
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)
Por fim, remova o uso do SDK de app.yaml (exclua a linha: app_engine_apis: true) e requirements.txt (exclua a linha: appengine-python-standard).
Migrar para o Cloud Memorystore (e o Cloud NDB)
O modelo de dados do Cloud NDB foi criado para ser compatível com o ndb do App Engine. Isso significa que a definição de objetos Visit permanece a mesma. Imitando a migração do módulo 2 para o Cloud NDB, todas as chamadas do Datastore em store_visit() e fetch_visits() são aumentadas e incorporadas em um novo bloco with, já que o uso do gerenciador de contexto do Cloud NDB é obrigatório. Confira as chamadas antes dessa mudança:
ANTES:
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)
Adicione um bloco with ds_client.context() às duas funções e coloque as chamadas do Datastore dentro dele (com recuo). Nesse caso, não é necessário fazer mudanças nas próprias chamadas:
AFTER:
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)
Em seguida, vamos analisar as mudanças no armazenamento em cache. Esta é a função main() do Módulo 12:
ANTES:
@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)
O Redis tem chamadas "get" e "set", assim como o Memcache. Tudo o que fazemos é trocar as bibliotecas de cliente respectivas, certo? Quase. Como mencionado anteriormente, não é possível armazenar em cache uma lista do Python com o Redis, porque ela precisa ser serializada primeiro, algo que o Memcache faz automaticamente. Portanto, na chamada set(), faça o "pickle" das visitas em uma string com pickle.dumps(). Da mesma forma, ao recuperar visitas do cache, é necessário usar pickle.loads() logo após o get(). Este é o gerenciador principal depois de implementar essas mudanças:
AFTER:
@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)
Concluímos as mudanças necessárias em main.py para converter o uso do Memcache pelo app de exemplo no Cloud Memorystore. E o modelo HTML e a portabilidade para o Python 3?
Atualizar o arquivo de modelo HTML e migrar para o Python 3?
Surpresa! Não é necessário fazer nada aqui, já que o aplicativo foi projetado para ser executado no Python 2 e 3 sem alterações no código nem bibliotecas de compatibilidade. Você vai encontrar main.py. idênticos nas pastas "FINISH" do mod13a (2.x) e do mod13b (3.x). O mesmo vale para requirements.txt , além de diferenças nos números de versão (se usados). Como a interface do usuário não muda, não há atualizações no templates/index.html.
Tudo o que é necessário para executar esse app no Python 3 do App Engine foi concluído anteriormente na configuração: diretivas desnecessárias foram removidas de app.yaml, e appengine_config.py e a pasta lib foram excluídos porque não são usados no Python 3.
7. Resumo/limpeza
Esta seção conclui o codelab implantando o app e verificando se ele funciona conforme o esperado e em qualquer saída refletida. Depois da validação do app, faça uma limpeza e pense nas próximas etapas.
Implantar e verificar o aplicativo
A última verificação é sempre implantar o app de exemplo. Desenvolvedores do Python 2: exclua e reinstale o lib com os comandos abaixo. Se você tiver o Python 2 e o 3 instalados no sistema, talvez seja necessário executar pip2 explicitamente.
rm -rf ./lib pip install -t lib -r requirements.txt
Agora, os desenvolvedores de Python 2 e 3 precisam implantar os apps com:
gcloud app deploy
Como você apenas reconectou as coisas por baixo dos panos para um serviço de armazenamento em cache completamente diferente, o app em si vai operar de maneira idêntica ao app do Módulo 12:

Esta etapa conclui o codelab. Compare o app de exemplo atualizado com uma das pastas do módulo 13, mod13a (Python 2) ou mod13b (Python 3).
Limpar
Geral
Se você terminou por enquanto, recomendamos que desative o app do App Engine para evitar cobranças. No entanto, se você quiser testar ou experimentar mais, a plataforma do App Engine tem uma cota sem custo financeiro. Portanto, enquanto você não exceder esse nível de uso, não vai receber cobranças. Isso é para computação, mas também pode haver cobranças por serviços relevantes do App Engine. Consulte a página de preços para mais informações. Se essa migração envolver outros serviços do Cloud, eles serão cobrados separadamente. Em qualquer caso, se aplicável, consulte a seção "Específico para este codelab" abaixo.
Para total transparência, a implantação em uma plataforma de computação sem servidor do Google Cloud, como o App Engine, gera custos mínimos de build e armazenamento. O Cloud Build e o Cloud Storage têm cotas sem custo financeiro próprias. O armazenamento dessa imagem usa parte dessa cota. No entanto, talvez você more em uma região que não tem um nível sem custo financeiro. Por isso, fique de olho no uso do armazenamento para minimizar possíveis custos. As "pastas" específicas do Cloud Storage que você precisa analisar incluem:
console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/imagesconsole.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com- Os links de armazenamento acima dependem da sua
PROJECT_IDe *LOC*ação. Por exemplo, "us" se o app estiver hospedado nos EUA.
Por outro lado, se você não quiser continuar com este aplicativo ou outros codelabs de migração relacionados e quiser excluir tudo completamente, desligue seu projeto.
Específico para este codelab
Os serviços listados abaixo são exclusivos deste codelab. Consulte a documentação de cada produto para mais informações:
- O Cloud Memorystore exige instâncias e não tem um nível sem custo financeiro. Para saber mais sobre os custos de uso, consulte a página de preços.
- Os conectores de acesso VPC sem servidor do Cloud exigem instâncias e não têm um nível sem custo financeiro. Para saber mais sobre os custos de uso, consulte a seção correspondente na página de preços da VPC do Cloud.
- O Cloud Datastore (Cloud Firestore no modo Datastore) tem um nível sem custo financeiro. Consulte a página de preços para mais informações.
Neste tutorial, usamos quatro produtos do Cloud:
- App Engine
- Cloud Datastore
- Cloud Memorystore
- Cloud VPC
Confira abaixo as instruções para liberar esses recursos e evitar/minimizar cobranças.
Desativar a instância do Memorystore e o conector de VPC
Esses são os produtos sem um nível sem custo financeiro, então você está recebendo cobranças agora. Se você não encerrar o projeto do Cloud (consulte a próxima seção), será necessário excluir a instância do Memorystore e o conector da VPC para interromper o faturamento. Assim como na criação desses recursos, você também pode liberá-los no console do Cloud ou na linha de comando.
No Console do Cloud
Para excluir a instância do Memorystore, volte ao painel do Memorystore e clique no ID da instância:

Na página de detalhes da instância, clique em "Excluir" e confirme:
Para excluir o conector de VPC, acesse o painel dele, marque a caixa de seleção ao lado do conector que você quer excluir, clique em "Excluir" e confirme:

Na linha de comando
O par de comandos gcloud a seguir exclui a instância do Memorystore e o conector de VPC, respectivamente:
gcloud redis instances delete INSTANCE --region REGIONgcloud compute networks vpc-access connectors delete CONNECTOR --region REGION
Se você não tiver definido o ID do projeto com gcloud config set project, talvez seja necessário fornecer --project PROJECT_ID. Se a instância do Memorystore for chamada de demo-ms e o conector de VPC de demo-vpc, e ambos estiverem na região us-central1, execute o seguinte par de comandos e confirme:
$ 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].
Cada solicitação leva alguns minutos para ser executada. Essas etapas são opcionais se você optar por desligar todo o projeto na nuvem, conforme descrito anteriormente. No entanto, o faturamento será cobrado até que o processo de desligamento seja concluído.
Próximas etapas
Além deste tutorial, outros módulos de migração que se concentram em migrar dos serviços agrupados legados incluem:
- Módulo 2: migrar do App Engine
ndbpara o Cloud NDB - Módulos 7 a 9: migrar das tarefas push da fila de tarefas do App Engine para o Cloud Tasks
- Módulos 12 e 13: migrar do Memcache do App Engine para o Cloud Memorystore
- Módulos 15 e 16: migrar do Blobstore do App Engine para o Cloud Storage
- Módulos 18 e 19: migrar da fila de tarefas do App Engine (tarefas pull) para o Cloud Pub/Sub
O App Engine não é mais a única plataforma sem servidor no Google Cloud. Se você tem um app pequeno do App Engine ou um com funcionalidade limitada e quer transformá-lo em um microsserviço independente, ou se quer dividir um app monolítico em vários componentes reutilizáveis, esses são bons motivos para considerar a migração para o Cloud Functions. Se a contêinerização se tornou parte do seu fluxo de trabalho de desenvolvimento de aplicativos, principalmente se ele consistir em um pipeline de CI/CD (integração contínua/entrega ou implantação contínua), considere migrar para o Cloud Run. Esses cenários são abordados nos seguintes módulos:
- Migrar do App Engine para o Cloud Functions: consulte o Módulo 11
- Migrar do App Engine para o Cloud Run: consulte o Módulo 4 para contentorizar seu app com o Docker ou o Módulo 5 para fazer isso sem contêineres, conhecimento do Docker ou
Dockerfiles
A mudança para outra plataforma sem servidor é opcional. Recomendamos considerar as melhores opções para seus apps e casos de uso antes de fazer qualquer mudança.
Independente do módulo de migração que você considerar em seguida, todo o conteúdo da Estação de migração sem servidor (codelabs, vídeos, código-fonte [quando disponível]) pode ser acessado no repositório de código aberto. O README do repositório também oferece orientações sobre quais migrações considerar e a "ordem" relevante dos módulos de migração.
8. Outros recursos
Confira abaixo mais recursos para desenvolvedores que querem saber mais sobre este ou outros módulos de migração e produtos relacionados. Isso inclui locais para enviar feedback sobre o conteúdo, links para o código e vários documentos que podem ser úteis.
Problemas/feedback dos codelabs
Se você encontrar problemas com este codelab, pesquise seu problema antes de preenchê-lo. Links para pesquisar e criar novos problemas:
Recursos de migração
Os links para as pastas do repositório do módulo 12 (START) e do Módulo 13 (FINISH) podem ser encontrados na tabela abaixo. Elas também podem ser acessadas no repositório de todas as migrações de codelab do App Engine, que você pode clonar ou fazer o download de um arquivo ZIP.
Codelab | Python 2 | Python 3 |
Módulo 13 (este codelab) |
Referências on-line
Confira abaixo recursos on-line que podem ser relevantes para este tutorial:
App Engine
- Documentação do App Engine
- Tempo de execução do Python 2 no App Engine (ambiente padrão)
- Como usar bibliotecas integradas do App Engine no App Engine do Python 2
- Tempo de execução do Python 3 no App Engine (ambiente padrão)
- Diferenças entre os ambientes de execução do Python 2 e 3 no App Engine (ambiente padrão)
- Guia de migração do App Engine (ambiente padrão) do Python 2 para o 3
- Informações sobre preços e cotas do App Engine
NDB do App Engine e NDB do Cloud
- Visão geral do App Engine NDB
- Uso do NDB Datastore do App Engine
- Documentos do Google Cloud NDB
- Repositório do Google Cloud NDB
- Informações de preços do Cloud Datastore
Memcache do App Engine e Cloud Memorystore
- Visão geral do Memcache do App Engine
- Referência do App Engine
memcachepara Python 2 - Referência do App Engine
memcachepara Python 3 - Guia de migração do App Engine
memcachepara o Cloud Memorystore - Documentação do Cloud Memorystore
- Documentação do Cloud Memorystore para Redis
- Informações de preços do Cloud Memorystore para Redis
- Versões do Redis compatíveis com o Cloud Memorystore
- Página inicial do Cloud Memorystore
- Criar uma instância do Memorystore no Console do Cloud
- Página inicial do cliente Python Redis
- Documentação da biblioteca de cliente Python Redis
Cloud VPC
- Documentos da VPC do Google Cloud
- Página inicial da VPC do Google Cloud
- Informações de preços da VPC do Google Cloud
- Criar um conector de acesso VPC sem servidor no Cloud Console
Outras informações da nuvem
- Python no Google Cloud Platform
- Bibliotecas de cliente do Python para Google Cloud
- Nível "Sempre sem custo financeiro" do Google Cloud
- SDK do Google Cloud (ferramenta de linha de comando
gcloud) - Toda a documentação do Google Cloud
Licença
Este conteúdo está sob a licença Atribuição 2.0 Genérica da Creative Commons.
