Módulo 2: Migrar do App Engine ndb para o Cloud NDB

Esta série de codelabs (tutoriais práticos e autoguiados) destina-se a ajudar os desenvolvedores do Google App Engine (Padrão) a modernizar os aplicativos por meio de uma série de migrações. A etapa mais significativa é deixar de usar os serviços originais de pacote em tempo de execução porque os ambientes de execução de última geração são mais flexíveis, oferecendo aos usuários uma variedade maior de opções de serviços. A migração para o ambiente de execução de geração mais recente permite uma integração com os produtos do Google Cloud mais facilmente, usa uma variedade maior de serviços compatíveis e oferece suporte às versões de linguagem atuais.

Neste tutorial, você verá como migrar da biblioteca de cliente (ndb Database) integrada do App Engine para a biblioteca de cliente do Cloud NDB.

Você aprenderá como realizar as seguintes tarefas:

  • Use a biblioteca ndb do App Engine, se você não estiver familiarizado com ela.
  • Migrar de ndb para o Cloud NDB
  • Migração adicional do aplicativo para Python 3

Pré-requisitos

Pesquisa

Como você usará este codelab?

Apenas leitura Leitura e exercícios

No Módulo 1, migramos os frameworks da Web do webapp2 integrado do App Engine para o Flask. Neste codelab, continuamos migrando dos serviços integrados do App Engine alternando da biblioteca ndb do App Engine para o Cloud NDB do Google.

Após concluir essa migração, você poderá:

  1. Migre para o Python 3 e o ambiente de execução de última geração do App Engine
  2. Migrar para o Cloud Datastore (biblioteca de cliente para aplicativos que não são do App Engine)
  3. Coloque em contêiner seu app Python 2 (ou 3) e migre para o Cloud Run
  4. Adicione o uso de filas de tarefas (push) do App Engine e migre para o Cloud Tasks

Ainda não chegamos lá. Conclua este codelab antes de considerar as próximas etapas. A migração deste tutorial apresenta as seguintes etapas principais:

  1. Configuração/Pré-trabalho
  2. Adicionar biblioteca do Cloud NDB
  3. Atualizar arquivos do aplicativo

Antes de prosseguirmos com a parte principal do tutorial, vamos configurar o nosso projeto, obter o código e, em seguida, implantar o aplicativo de referência para saber que começamos a trabalhar com o código em funcionamento.

1. Configurar projeto

Se você concluiu o codelab do Módulo 1, recomendamos a reutilização desse mesmo projeto e código. Se preferir, crie um novo projeto ou reutilize outro. Verifique se o projeto tem uma conta de faturamento ativa e se o App Engine está ativado.

2. Receber app de amostra do valor de referência

Um dos pré-requisitos é ter um aplicativo de amostra do Módulo 1 que funcione. Use sua solução se você concluiu esse tutorial. Você pode concluir isso (link acima) ou, se quiser, ignorar o repositório e copiar o repositório do módulo 1 (link abaixo).

Independentemente de você usar o nosso ou o nosso, o código do Módulo 1 é o que faremos. Este codelab do Módulo 2 orienta você em cada etapa e, quando concluído, deve ser semelhante ao código no ponto FINISH (incluindo uma porta "bônus" opcional do Python 2 a 3):

A pasta de código do Módulo 1 deve ter o seguinte conteúdo:

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

Se você concluiu o tutorial do Módulo 1, também terá uma pasta lib com o Flask e as dependências correspondentes. Se você não tiver uma pasta lib, crie-a com o comando pip install -t lib -r requirements.txt para que possamos implantar esse aplicativo de referência na próxima etapa. Se você tiver o Python 2 e o 3 instalados, recomendamos usar pip2 em vez de pip para evitar confusões com o Python 3.

3. (Re)Implantar aplicativo do módulo 1

As etapas de pré-trabalho restantes para serem executadas agora:

  1. Familiarize-se com a ferramenta de linha de comando do gcloud (se necessário).
  2. (Re)implantar o código do Módulo 1 no App Engine (se necessário)

Depois que você concluir essas etapas e confirmar que está em operação, seguiremos neste tutorial, começando com os arquivos de configuração.

Muitos serviços integrados originais do App Engine são florados nos seus próprios produtos, e o Datastore é um deles. Hoje, os aplicativos que não são do App Engine podem usar o Cloud Datastore. Para usuários ndb de longa duração, a equipe do Google Cloud criou a biblioteca de cliente do Cloud NDB para se comunicar com o Cloud Datastore. Ela está disponível para Python 2 e 3.

Vamos atualizar os arquivos de confirmação para substituir o App Engine ndb pelo Cloud NDB e, em seguida, modificar nosso aplicativo.

1. Atualizar requirements.txt

No Módulo 1, a única dependência externa do nosso aplicativo foi o Flask. Agora, vamos adicionar o Cloud NDB. Esta é a aparência do arquivo requirements.txt no fim do Módulo 1:

  • Antes:
Flask==1.1.2

A migração do App Engine ndb requer a biblioteca do Cloud NDB (google-cloud-ndb), portanto, adicione seu pacote a requirements.txt.

  • Depois:
Flask==1.1.2
google-cloud-ndb==1.7.1

Quando este codelab foi escrito, a versão mais recente recomendada é 1.7.1, mas requirements.txt no repositório pode ter uma versão mais recente. Recomendamos as versões mais recentes de cada biblioteca, mas caso elas não funcionem, é possível reverter para uma versão mais antiga.

Exclua a pasta lib se você tiver uma, mas não a criou acima. Agora, reinstale as bibliotecas atualizadas com o comando pip install -t lib -r requirements.txt usando pip2 em vez de pip, conforme necessário.

2. Atualizar app.yaml

A adição de bibliotecas de cliente do Google Cloud, como google-cloud-ndb, tem alguns requisitos, todos girando em torno da inclusão de bibliotecas"integradas", pacotes de terceiros já disponíveis nos servidores do Google. Não as lista em requirements.txt nem você os copia com pip install. Os únicos requisitos:

  1. Especificar bibliotecas integradas em app.yaml
  2. Aponte para bibliotecas copiadas de terceiros com as quais eles podem trabalhar (em lib)

Esta é a app.yaml de criação do Módulo 1:

  • Antes:
runtime: python27
threadsafe: yes
api_version: 1

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

Agora, adicione as seguintes linhas ao app.yaml para fazer referência a um par de pacotes de terceiros: grpcio e setuptools em uma nova seção libraries:

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

Por que usar essas bibliotecas integradas? gRPC. é uma estrutura RPC aberta usada por todas as bibliotecas de cliente do Google Cloud:, incluindo google-cloud-ndb. A biblioteca grpcio é o adaptador gRPC do Python e, portanto, é necessária. O raciocínio por incluir setuptools está chegando.

  • Depois:

Com as alterações acima, seu app.yaml atualizado 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

3. Atualizar appengine_config.py

A ferramenta pkg_resources, parte da biblioteca setuptools, é usada para permitir que bibliotecas de terceiros integradas acessem as pacotes. Atualize o appengine_config.py para usar o pkg_resources e direcioná-los às bibliotecas empacotadas em lib. Quando você concluir essa alteração, o arquivo todo terá a seguinte aparência:

import pkg_resources
from google.appengine.ext import vendor

# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
# Add libraries to pkg_resources working set to find the distribution.
pkg_resources.working_set.add_entry(PATH)

Com a formalidade do arquivo de configuração, agora é possível migrar de ndb para o Cloud NDB. Para concluir a migração, atualize as bibliotecas importadas e adicione o uso do gerenciamento de contexto ao main.py.

1. Importações

Faça a seguinte troca de importação em main.py:

  • ANTES
from google.appengine.ext import ndb
  • Depois:
from google.cloud import ndb

As mudanças de uma biblioteca do App Engine para uma biblioteca do Google Cloud pode ser tão sutis quanto essa instância. Para serviços integrados que se tornaram os produtos completos do Google Cloud, você importará atributos de google.cloud, em vez de google.appengine.

2. Acesso ao Datastore

Para usar a biblioteca do Cloud NDB, seu aplicativo precisa usar gerenciadores de contexto do Python. O objetivo deles é "forçar" o acesso a recursos para que eles sejam adquiridos antes de serem usados. Os gerenciadores de contexto são baseados na técnica de controle da ciência da computação conhecida como Alocação de recursos é inicialização (ou RAII). Gerenciadores de contexto são usados com arquivos Python (que precisam ser abertos antes de serem acessados) e simultaneidade, "bloqueios de pino" devem ser adquiridos antes do código em uma seção crítica possa ser executada.

Da mesma forma, o Cloud NDB requer a aquisição do contexto de um cliente para comunicação com o Datastore antes de executar qualquer comando do Datastore. Primeiro, crie um cliente (ndb.Client()) adicionando ds_client = ndb.Client() em main.py logo após a inicialização do Flask:

app = Flask(__name__)
ds_client = ndb.Client()

O comando Python with é usado exclusivamente para acessar o contexto de um objeto. Agrupe todos os blocos de código que acessam o Datastore com instruções with.

Veja abaixo as mesmas funções do Módulo 1 para gravar uma nova Entidade no Datastore e leitura para exibir as Entidades adicionadas mais recentemente:

  • Antes:

Veja o código original sem gerenciamento de contexto:

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 (v.to_dict() for v in Visit.query().order(
            -Visit.timestamp).fetch(limit))
  • Depois:

Agora, adicione with ds_client.context(): e mova o código de acesso do Datastore para o bloco with:

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

O aplicativo principal do driver permanece idêntico ao que tínhamos no Módulo 1 porque não há código ndb (nem Cloud NDB) aqui:

@app.route('/')
def root():
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)
    return render_template('index.html', visits=visits)

Uma prática recomendada é garantir uma distinção clara entre o código do aplicativo e o acesso aos dados. Dessa forma, o código do aplicativo principal não é alterado quando o mecanismo de armazenamento de dados subjacente é alterado, como fizemos com essa migração.

Implante o aplicativo

Implante o app novamente com gcloud app deploy e confirme se ele funciona. Seu código agora deve corresponder ao que está no repositório do módulo 2.

Se você passou para esta série sem fazer qualquer um dos codelabs anteriores, o app em si não muda. Ele registra todas as visitas à página principal da web (/) e tem esta aparência quando o site é acessado muitas vezes:

app visitme

Parabéns! Você concluiu este codelab Module 2. Você ultrapassou a linha de conclusão, já que esta é a última das migrações altamente recomendadas desta série até o Datastore.

Opcional: limpar

E a limpeza para evitar cobrança até que você esteja pronto para passar para o próximo codelab de migração? Como você, os desenvolvedores já estão atualizados nas informações de preços do App Engine.

Opcional: desativar app

Se você ainda não estiver pronto para avançar para o próximo tutorial, desative seu app para evitar cobranças. Quando estiver pronto para passar para o próximo codelab, você poderá reativá-lo. Enquanto seu aplicativo estiver desativado, ele não receberá tráfego para custos. No entanto, o uso do Datastore pode ser cobrado se exceder a cota gratuita, Exclua o suficiente para ficar abaixo desse limite.

Por outro lado, se você não quiser continuar com as migrações e quiser excluir tudo completamente, poderá encerrar seu projeto.

Próximas etapas

Aqui, você tem flexibilidade para a próxima etapa. Escolha uma destas opções:

  • Bônus do módulo 2: continue abaixo da parte de cortesia deste tutorial para explorar a portabilidade para o Python 3 e a próxima geração do ambiente de execução do App Engine.
  • Módulo 7: filas de tarefas push do App Engine (obrigatório se você usar filas de tarefas [push]
    • Adiciona tarefas push taskqueue do App Engine ao aplicativo Module 1
    • Prepara os usuários a migrar para o Cloud Tasks no Módulo 8
  • Módulo 4: migre para o Cloud Run com o Docker
    • Contentorize seu app para ser executado no Cloud Run com o Docker
    • Permite que você se mantenha no Python 2
  • Módulo 5: Migrar para o Cloud Run com o Cloud Buildpacks
    • Contentorize seu app para ser executado no Cloud Run com o Cloud Buildpacks
    • Não é preciso saber nada sobre o Docker, os contêineres ou as Dockerfiles.
    • Exige que você já tenha migrado seu aplicativo para Python 3.
  • Módulo 3:
    • Modernize o acesso ao Datastore do Cloud NDB para o Cloud Datastore
    • Esta é a biblioteca usada para aplicativos do App Engine em Python 3 e aplicativos que não são do App Engine

Para acessar os ambientes de execução e recursos mais recentes do App Engine, recomendamos que você migre para o Python 3. Em nosso aplicativo de amostra, o Datastore foi o único serviço integrado que usamos e, como migramos de ndb para o Cloud NDB, agora podemos fazer a portabilidade para o ambiente de execução do Python 3 do App Engine.

Visão geral

Embora a transferência para o Python 3 não esteja no escopo de um tutorial do Google Cloud, esta parte do codelab dá aos desenvolvedores uma ideia da diferença entre o tempo de execução do Python 3 do App Engine. Um recurso excelente do ambiente de execução de última geração é o acesso simplificado a pacotes de terceiros. Não é necessário especificar pacotes incorporados em app.yaml nem é necessário copiar ou fazer upload de bibliotecas não integradas. Eles são instalados implicitamente na lista de requirements.txt.

Como nossa amostra é tão básica e o Cloud NDB é compatível com o Python 2-3, nenhum código de aplicativo precisa ser explicitamente transferido para 3.x. O aplicativo é executado nas versões 2.x e 3.x não modificadas, o que significa que as únicas alterações obrigatórias estão na configuração neste caso:

  1. Simplifique o app.yaml para referenciar o Python 3 e remover bibliotecas de terceiros.
  2. Exclua appengine_config.py e a pasta lib, já que não são mais necessárias.

Além de main.py, os arquivos requirements.txt e templates/index.html permanecem inalterados.

Simplesmente app.yaml

Antes:

A única alteração real para este aplicativo de amostra é reduzir app.yaml de forma significativa. Como lembrete, veja o que tivemos em app.yaml após a conclusão do Módulo 2:

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

Depois:

No Python 3, as diretivas threadsafe, api_version e libraries estão obsoletas. Todos os aplicativos são presumidos, e api_version não é usado no Python 3. Não há mais pacotes integrados de terceiros pré-instalados nos serviços do App Engine, por isso libraries também está obsoleto. Consulte a documentação sobre alterações no app.yaml para ver mais informações sobre essas mudanças. Por isso, você precisa excluir os três em app.yaml e atualizar para uma versão compatível do Python 3 (veja abaixo).

Uso da diretiva handlers

Além disso, a diretiva handlers, que direciona o tráfego nos aplicativos do App Engine, também foi desativada. Como o ambiente de execução de última geração espera que as bibliotecas da Web gerenciem o roteamento de aplicativos, todos os "scripts do gerenciador" precisam ser alterados para "auto". Combinando as alterações acima, você chega à seguinte app.yaml:

runtime: python38

handlers:
- url: /.*
  script: auto

Saiba mais sobre script: auto na página de documentação.

Diretiva de remoção handlers

Como handlers está obsoleto, também é possível remover toda a seção, deixando um app.yaml de linha única:

runtime: python38

Por padrão, o servidor da Web WSGI do Gunicorn será disponibilizado para todos os apps por padrão. Se você estiver familiarizado com gunicorn, este é o comando executado quando ele é iniciado por padrão com o barebones app.yaml:

gunicorn main:app --workers 2 -c /config/gunicorn.py

Opcional: uso da diretiva entrypoint

No entanto, se o aplicativo exigir um comando de inicialização específico, isso pode ser especificado com uma diretiva entrypoint em que app.yaml seria semelhante a:

runtime: python38
entrypoint: python main.py

Este exemplo solicita especificamente que o servidor de desenvolvimento Flask seja usado em vez de gunicorn. O código que inicia o servidor de desenvolvimento também precisa ser adicionado ao app para ser iniciado na interface 0.0.0.0 na porta 8080. Basta adicionar esta pequena seção à parte inferior de main.py:

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)

Saiba mais sobre entrypoint na página de documentação. Encontre mais exemplos e práticas recomendadas nos documentos de inicialização padrão do App Engine e a documentação de inicialização flexível do App Engine.

Excluir appengine_config.py e lib

Exclua o arquivo appengine_config.py e a pasta lib. Na migração para o Python 3, o App Engine adquire e instala pacotes listados em requirements.txt.

O arquivo de configuração appengine_config.py é usado para reconhecer bibliotecas/pacotes de terceiros, sejam eles copiados ou usados por servidores já disponíveis nos servidores do App Engine (integrados). Na migração para o Python 3, um resumo das principais mudanças são:

  1. Nenhum agrupamento de bibliotecas de terceiros copiadas (listadas em requirements.txt)
  2. Não há pip install em uma pasta lib, o que significa que não há um período de pasta lib
  3. Nenhuma ficha integrada de terceiros no app app.yaml
  4. Não é necessário referenciar o aplicativo para as bibliotecas de terceiros. Portanto, nenhum arquivo appengine_config.py

Para listar todas as bibliotecas de terceiros necessárias em requirements.txt é tudo o que é necessário.

Implante o aplicativo

Implante o app novamente para garantir que ele funcione. Você também pode confirmar se a solução está perto do código 2 do Python 3 de exemplo do módulo. Para visualizar as diferenças com o Python 2, compare o código com sua versão do Python 2.

Parabéns pela conclusão da etapa bônus no Módulo 2! Acesse a documentação sobre como preparar arquivos de configuração para o ambiente de execução do Python 3. Por fim, volte para a etapa anterior de "Resumo/Limpeza" para ver as próximas etapas e fazer a limpeza.

Como preparar seu aplicativo

Na hora de migrar seu aplicativo, será preciso fazer a portabilidade dos main.py e outros arquivos do aplicativo para 3.x. Portanto, uma prática recomendada é fazer o melhor para que a 2.x aplicativo o mais rápido possível.

Há vários recursos on-line para ajudar a fazer isso, mas algumas das principais dicas:

  1. Garanta que todas as dependências do aplicativo sejam totalmente compatíveis com 3.x
  2. Verifique se o app é executado em, pelo menos, a versão 2.6 (preferencialmente, a versão 2.7).
  3. Garantir que o aplicativo passe por todo o conjunto de testes (e, no mínimo, 80% de cobertura)
  4. Use bibliotecas de compatibilidade como six, Future e/ou Modernize
  5. Informe-se sobre as principais diferenças incompatíveis com versões anteriores x 2.x
  6. Qualquer E/S provavelmente gerará incompatibilidades de Unicode x string de byte

O aplicativo de amostra foi projetado com tudo isso em mente, então o motivo de ele ser executado nas versões 2.x e 3.x para que possamos focar em mostrar o que precisa ser alterado para usar a plataforma de última geração.

Problemas/comentários do módulo de migração do App Engine

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 1 (START) e do Módulo 2 (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 1

código

(n/a)

Módulo 2

código

código

Recursos do App Engine

Veja abaixo mais recursos relacionados a essa migração específica: