Módulo 3: Migrar do Google Cloud NBS para o Cloud Datastore

1. Visão geral

Esta série de codelabs (tutoriais práticos e autoguiados) destina-se a ajudar os desenvolvedores do Google App Engine (ambiente 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.

Este tutorial opcional mostra aos desenvolvedores como migrar do Cloud NDB para o Cloud Datastore como a biblioteca de cliente para se comunicar com o serviço do Datastore. Os desenvolvedores que preferem o NDB podem continuar usando essa biblioteca, já que ela é compatível com o Python 3. Por isso, essa migração é opcional. Essa migração é apenas para quem quer criar uma base de código consistente e bibliotecas compartilhadas com outros apps que já usam o Cloud Datastore. Isso é explicado na seção "Contexto".

Você aprenderá como realizar as seguintes tarefas:

  • Use o Cloud NDB, se você não estiver familiarizado com ele.
  • Migrar do Cloud NDB para o Cloud Datastore
  • Migração adicional do aplicativo para Python 3

O que é necessário

  • Um projeto do Google Cloud Platform com uma conta de faturamento do GCP ativa
  • Habilidades básicas em Python
  • Conhecimento prático dos comandos básicos do Linux
  • Conhecimento básico sobre o desenvolvimento e a implantação de apps do App Engine
  • Um aplicativo 2.x ou 3.x do App Engine do módulo 2 em funcionamento.

Pesquisa

Como você usará este codelab?

Apenas leitura Leitura e exercícios

2. Contexto

Embora o Cloud NDB seja uma ótima solução do Datastore para desenvolvedores do App Engine há muito tempo e ajude na transição para o Python 3, não é a única maneira de os desenvolvedores do App Engine acessarem o Datastore. Quando o Datastore do App Engine se tornou um produto independente em 2013, o Google Cloud Datastore, uma nova biblioteca de cliente, foi criado para que todos os usuários pudessem usar o Datastore.

Os desenvolvedores do App Engine em Python 3 e não-App Engine são direcionados a usar o Cloud Datastore (não o Cloud NDB). Recomendamos que os desenvolvedores do App Engine Python 2 migrem do ndb para o Cloud NDB e façam a portabilidade para o Python 3. No entanto, também é possível migrar para o Cloud Datastore. Essa é uma decisão lógica, especialmente para desenvolvedores que já têm código usando o Cloud Datastore, como os mencionados acima, e querem criar bibliotecas compartilhadas em todos os aplicativos. A reutilização e a consistência do código são práticas recomendadas que contribuem para a redução geral do custo de manutenção, conforme resumido aqui:

Migração do Cloud NDB para o Cloud Datastore

  • Permite que os desenvolvedores se concentrem em uma única base de código para acesso ao Datastore
  • Evita manter alguns códigos usando o Cloud NDB e outros usando o Cloud Datastore
  • Oferece mais consistência na base de código e melhor capacidade de reutilização do código.
  • Permite o uso de bibliotecas comuns/compartilhadas, o que contribui para reduzir o custo geral de manutenção.

Essa migração tem as seguintes etapas principais:

  1. Configuração/Pré-trabalho
  2. Substituir o Cloud NDB pelas bibliotecas de cliente do Cloud Datastore
  3. Atualizar aplicativo

3. Configuração/Pré-trabalho

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 2, recomendamos reutilizar esse 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 o App Engine (aplicativo) está ativado.

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

Um dos pré-requisitos é ter um app de exemplo do Módulo 2 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 2 (link abaixo).

Independentemente de você usar o seu ou o nosso, o código do Módulo 2 é o que faremos. Este codelab do Módulo 3 orienta você em cada etapa e, quando concluído, deve ser semelhante ao código no ponto FINISH. Há versões em Python 2 e 3 deste tutorial. Portanto, acesse o repositório de código correto abaixo.

Python 2

O diretório do Python 2 do Module 2 (os seus arquivos ou os nossos) deve ter a seguinte aparência:

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

Se você concluiu o tutorial do Módulo 2, 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.

Python 3

O diretório do Python 3 do Module 2 (os seus arquivos ou os nossos) deve ter a seguinte aparência:

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

Nem lib nem appengine_config.py são usados para Python 3.

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

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.

4. Substituir o Cloud NDB pelas bibliotecas de cliente do Cloud Datastore

A única mudança de configuração é uma pequena troca de pacote no arquivo requirements.txt.

1. Atualizar requirements.txt

Depois de concluir o Módulo 2, o arquivo requirements.txt ficou assim:

  • ANTES (Python 2 e 3):
Flask==1.1.2
google-cloud-ndb==1.7.1

Atualize requirements.txt substituindo a biblioteca do Cloud NDB (google-cloud-ndb) pela versão mais recente da biblioteca do Cloud Datastore (google-cloud-datastore), deixando a entrada do Flask intacta. A versão final do Cloud Datastore compatível com Python 2 é a 1.15.3:

  • DEPOIS (Python 2):
Flask==1.1.2
google-cloud-datastore==1.15.3
  • DEPOIS (Python 3):
Flask==1.1.2
google-cloud-datastore==2.1.0

O repositório é atualizado com mais frequência do que este tutorial. Por isso, é possível que o arquivo requirements.txt reflita versões mais recentes. Recomendamos as versões mais recentes de cada biblioteca, mas caso elas não funcionem, é possível reverter para uma versão mais antiga. Os números de versão acima são os mais recentes quando este codelab foi atualizado pela última vez.

2. Outros arquivos de configuração

Os outros arquivos de configuração, app.yaml e appengine_config.py, devem permanecer inalterados da etapa de migração anterior:

  • app.yaml ainda precisa fazer referência aos pacotes de terceiros grpcio e setuptools.
  • appengine_config.py ainda precisa apontar pkg_resources e google.appengine.ext.vendor para os recursos de terceiros em lib.

Agora vamos para os arquivos do aplicativo.

5. Atualizar arquivos do aplicativo

Não há mudanças em template/index.html, mas há algumas atualizações para main.py.

1. Importações

O código inicial da seção de importação deve ser assim:

  • Antes:
from flask import Flask, render_template, request
from google.cloud import ndb

Substitua a importação google.cloud.ndb por uma do Cloud Datastore: google.cloud.datastore. Como a biblioteca de cliente do Datastore não é compatível com a criação automática de um campo de carimbo de data/hora em uma entidade, importe também o módulo datetime da biblioteca padrão para criar um manualmente. Por convenção, as importações de bibliotecas padrão ficam acima das importações de pacotes de terceiros. Quando você terminar essas mudanças, o código vai ficar assim:

  • Depois:
from datetime import datetime
from flask import Flask, render_template, request
from google.cloud import datastore

2. Inicialização e modelo de dados

Depois de inicializar o Flask, o app de exemplo do módulo 2 que cria uma classe de modelo de dados NDB e seus campos tem esta aparência:

  • Antes:
app = Flask(__name__)
ds_client = ndb.Client()

class Visit(ndb.Model):
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)

A biblioteca do Cloud Datastore não tem essa classe. Portanto, exclua a declaração de classe Visit. Você ainda precisa de um cliente para se comunicar com o Datastore. Portanto, mude ndb.Client() para datastore.Client(). A biblioteca do Datastore é mais "flexível", permitindo que você crie entidades sem "pré-declarar" a estrutura delas, como o NDB. Depois dessa atualização, essa parte de main.py vai ficar assim:

  • Depois:
app = Flask(__name__)
ds_client = datastore.Client()

3. Acesso ao Datastore

A migração para o Cloud Datastore exige mudar a forma como você cria, armazena e consulta entidades do Datastore (no nível do usuário). Para seus aplicativos, a dificuldade dessa migração depende da complexidade do seu código do Datastore. No nosso app de exemplo, tentamos simplificar ao máximo a atualização. Este é o código inicial:

  • Antes:
def store_visit(remote_addr, user_agent):
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

def fetch_visits(limit):
    with ds_client.context():
        return (v.to_dict() for v in Visit.query().order(
                -Visit.timestamp).fetch_page(limit)[0])

Com o Cloud Datastore, crie uma entidade genérica, identificando objetos agrupados na sua entidade com uma "chave". Crie o registro de dados com um objeto JSON (Python dict) de pares de chave-valor e grave no Datastore com o put() esperado. A consulta é semelhante, mas mais simples com o Datastore. Aqui você pode ver como o código equivalente do Datastore é diferente:

  • Depois:
def store_visit(remote_addr, user_agent):
    entity = datastore.Entity(key=ds_client.key('Visit'))
    entity.update({
        'timestamp': datetime.now(),
        'visitor': '{}: {}'.format(remote_addr, user_agent),
    })
    ds_client.put(entity)

def fetch_visits(limit):
    query = ds_client.query(kind='Visit')
    query.order = ['-timestamp']
    return query.fetch(limit=limit)

Atualize os corpos das funções para store_visit() e fetch_visits() como acima, mantendo as assinaturas idênticas à versão anterior. Não há mudanças no manipulador principal root(). Depois de concluir essas mudanças, seu app estará pronto para usar o Cloud Datastore e poderá ser testado.

6. Resumo/limpeza

Implante o aplicativo

Implante o app novamente com gcloud app deploy e confirme se ele funciona. Agora, seu código precisa corresponder ao que está nas pastas do repositório do módulo 3:

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 por concluir este codelab do Módulo 3. Agora você sabe que pode usar as bibliotecas de cliente do Cloud NDB e do Cloud Datastore para acessar o Datastore. Ao migrar para o último, você pode aproveitar os benefícios de bibliotecas compartilhadas, código comum e reutilização de código para consistência e redução do custo de manutenção.

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 app estiver desativado, ele não vai receber tráfego para gerar custos. No entanto, o uso do Datastore pode ser cobrado se exceder a cota sem custo financeiro. 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

Agora, confira estes módulos de migração:

  • Bônus do módulo 3:continue para a seção de bônus e saiba como fazer 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 6: Migrar para o Cloud Firestore
    • Migrar para o Cloud Firestore para acessar recursos do Firebase
    • O Cloud Firestore é compatível com o Python 2, mas este codelab está disponível apenas no Python 3.

7. BÔNUS: migrar para Python 3

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 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 Datastore é compatível com o Python 2-3, nenhum código do aplicativo precisa ser explicitamente transferido para 3.x. O app é executado nas versões 2.x e 3.x não modificadas, o que significa que as únicas mudanças obrigatórias estão na configuração neste caso:

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

Os arquivos de aplicativo main.py e templates/index.html permanecem inalterados.

Atualizar requirements.txt

A versão final do Cloud Datastore compatível com o Python 2 é a 1.15.3. Atualize requirements.txt com a versão mais recente do Python 3 (pode ser mais recente agora). Quando este tutorial foi escrito, a versão mais recente era 2.1.0. Edite essa linha para que ela fique assim (ou qualquer que seja a versão mais recente):

google-cloud-datastore==2.1.0

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 tínhamos em app.yaml após a conclusão do Módulo 3:

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

Opcional: 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 referência app.yaml.

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, resultando em um app.yaml semelhante a este:

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 referência app.yaml. Encontre mais exemplos e práticas recomendadas nos documentos de inicialização do ambiente padrão do App Engine e nos documentos de inicialização do ambiente 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 3 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 por concluir a etapa bônus no Módulo 3! Acesse a documentação sobre como preparar arquivos de configuração para o ambiente de execução do Python 3. Por fim, revise o resumo acima para conferir 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.

8. Outros recursos

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 2 (START) e do Módulo 3 (FINISH) podem ser encontrados na tabela abaixo. Elas também podem ser acessadas no repositório de todas as migrações do App Engine, que você pode clonar ou fazer o download de um arquivo ZIP.

Codelab

Python 2

Python 3

Módulo 2

código

código

Módulo 3

código

código

Recursos do App Engine

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