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 individualizados) tem como objetivo ajudar os desenvolvedores do Google App Engine (ambiente padrão) a modernizar apps, orientando-os em 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 NFS para o Cloud Datastore como a biblioteca de cliente para se comunicar com o serviço Datastore. Os desenvolvedores que preferem o Node.js podem permanecer com ele, já que ele é compatível com Python 3. Por isso, essa migração é opcional. Essa migração é destinada apenas às pessoas que querem criar uma base de código consistente e bibliotecas compartilhadas com outros aplicativos que já usam o Cloud Datastore. Isso é explicado na seção nesta seção.

Você aprenderá como realizar as seguintes tarefas:

  • Usar o Cloud NFS (se você não estiver familiarizado com ele)
  • Migrar do Cloud NBS 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 app do App Engine 2.x ou 3.x em funcionamento com o módulo 2.

Pesquisa

Como você usará este codelab?

Apenas ler o documento Ler e fazer os exercícios

2. Contexto

Embora o Cloud NFS seja uma ótima solução do Datastore para desenvolvedores experientes do App Engine e ajude na transição para o Python 3, essa não é a única maneira de os desenvolvedores do App Engine acessarem o Datastore. Quando o Datastore do App Engine se tornou próprio produto em 2013, o Google Cloud Datastore, uma nova biblioteca de cliente, foi criada para que todos os usuários pudessem usar o Datastore.

Desenvolvedores do App Engine para Python 3 e não do App Engine são instruídos a usar o Cloud Datastore (não o Cloud NBS). Recomendamos que os desenvolvedores do App Engine para Python 2 migrem de ndb para o Cloud NBS e a porta para o Python 3 de lá, mas também podem optar por 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 que acabamos de mencionar, e querem criar bibliotecas compartilhadas em todos os seus aplicativos. A reutilização de código é uma prática recomendada, assim como a consistência, e ambos contribuem para a redução do custo geral de manutenção, como resumido aqui:

Migração do Cloud NBS 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 NBS e outros usando o Cloud Datastore
  • Proporciona mais consistência na base de código e melhor reutilização do código
  • Permite o uso de bibliotecas comuns/compartilhadas, que contribuem para diminuir o custo geral de manutenção.

Essa migração apresenta estas etapas principais:

  1. Configuração/Pré-trabalho
  2. Substituir o Cloud NBS por 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 o 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 em funcionamento. Use sua solução se você concluiu o tutorial. Faça isso agora (link acima) ou, se quiser pular, copie o repositório do Módulo 2 (link abaixo).

Não importa se você usa o seu ou o nosso, é no código do Módulo 2 que vamos INICIAR. Este codelab do Módulo 3 orienta você em cada etapa e, quando concluído, deve se parecer com o código no ponto FINISH. Este tutorial tem versões Python 2 e 3, então use o repositório de códigos 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 dele. 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 dos arquivos INÍCIOS do Módulo 2 do Python 3 (os seus ou os nossos) deverá 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 o app 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 NBS por 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

Ao concluir o Módulo 2, seu arquivo requirements.txt se parece com este:

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

Atualize o requirements.txt substituindo a biblioteca do Cloud NBS (google-cloud-ndb) pela versão mais recente da biblioteca do Cloud Datastore (google-cloud-datastore). Mantenha a entrada do Flask intacta. Lembre-se de que 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 é mantido com mais frequência do que este tutorial. Portanto, é possível que o arquivo requirements.txt reflita versões mais recentes. Recomendamos usar as versões mais recentes de cada biblioteca. No entanto, se elas não funcionarem, será possível reverter para uma versão mais antiga. Os números de versão acima são os mais recentes da última atualização deste codelab.

2. Outros arquivos de configuração

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

  • app.yaml precisa (ainda) fazer referência aos pacotes agrupados de terceiros grpcio e setuptools.
  • O 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 no template/index.html, mas há algumas atualizações para main.py.

1. Importações

O código inicial da seção de importação será semelhante a este:

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

Substitua a importação google.cloud.ndb por uma para o Cloud Datastore: google.cloud.datastore. Como a biblioteca de cliente do Datastore não oferece suporte à criação automática de um campo de carimbo de data/hora em uma entidade, importe também o módulo da biblioteca padrão datetime para criar um manualmente. Por convenção, as importações de bibliotecas padrão superam as 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 vai criar uma classe de modelo de dados e os campos dele da seguinte forma:

  • 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 que um cliente se comunique com o Datastore. Portanto, altere ndb.Client() para datastore.Client(). A biblioteca do Datastore é mais "flexível", permitindo que você crie entidades sem "declarar previamente" a estrutura deles, como o NBS. Após essa atualização, esta parte do main.py ficará assim:

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

3. Acesso ao Datastore

Migrar para o Cloud Datastore requer a alteração da 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 código do Datastore. No nosso app de exemplo, tentamos simplificar ao máximo a atualização. Este é nosso 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. Em seguida, grave-o no Datastore com o put() esperado. As consultas são semelhantes, mas são mais diretas com o Datastore. Veja aqui as diferenças do código do Datastore equivalente:

  • 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 da função para store_visit() e fetch_visits() como acima, mantendo as assinaturas idênticas à versão anterior. Não há mudanças no gerenciador principal root(). Depois de concluir essas alterações, o app estará pronto para usar o Cloud Datastore e para os testes.

6. Resumo/limpeza

Implante o aplicativo

Implante o app novamente com gcloud app deploy e confirme se ele funciona. Agora, o código precisa corresponder ao que está nas pastas de 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 NFS e do Cloud Datastore para acessar o Datastore. Ao migrar para a segunda opção, você tem 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 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

A partir daqui, fique à vontade para explorar os próximos módulos de migração:

  • Bônus do módulo 3:continue na seção de bônus para aprender a fazer a portabilidade para o Python 3 e o ambiente de execução do App Engine de última geração.
  • 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 precisa saber nada sobre o Docker, contêineres ou 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 é preciso especificar pacotes integrados no app.yaml nem exigir copiar ou fazer upload de bibliotecas não integradas. eles são implicitamente instalados da lista em requirements.txt.

Como nosso exemplo é muito básico e o Cloud Datastore é compatível com Python 2-3, nenhum código de aplicativo precisa ser explicitamente transferido para 3.x: o aplicativo é executado em 2.x e 3.x sem modificações, o que significa que as únicas alterações necessárias estão na configuração neste caso:

  1. Simplificamos 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 com suporte ao Python 2 é a 1.15.3. Atualize requirements.txt com a versão mais recente para Python 3 (pode ser mais recente agora). Quando este tutorial foi escrito, a versão mais recente era a 2.1.0, então edite a 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. Confira o que fizemos no app.yaml ao concluir o 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 do 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, que pode ser especificado com uma diretiva entrypoint, resultando em um app.yaml parecido com 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 do app.yaml. Veja mais exemplos e práticas recomendadas nos documentos de inicialização do ambiente padrão do App Engine e nos documentos sobre 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á próxima do exemplo de código Python 3 do módulo 3. 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 do 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 anterior para ver as próximas etapas e 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 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: