Módulo 6: Migrar do Cloud Datastore para o Cloud Firestore

1. Visão geral

Esta série de codelabs (tutoriais práticos e individualizados) tem como objetivo ajudar os desenvolvedores do Google App Engine (Standard) a modernizar os apps, orientando-os em uma série de migrações. A maioria dessas migrações envolve a substituição dos serviços incluídos no ambiente de execução original porque os ambientes de execução de última geração são mais flexíveis, oferecendo aos usuários uma maior variedade de opções de serviços. Outra maneira de modernizar um app inclui fazer upgrade para um produto mais recente, e esse é o assunto deste codelab.

Os usuários do App Engine que acessam o Datastore com as bibliotecas de cliente do Cloud NFS ou do Cloud Datastore podem começar a usar o produto e não precisam migrar. No entanto, o Cloud Firestore representa o repositório de dados NoSQL mais recente, escalonável e altamente disponível, com recursos do banco de dados em tempo real do Firebase.

Você está no lugar certo se é um desenvolvedor que se sente compelido a usar o Firestore para aproveitar os recursos ou pelo menos ter interesse suficiente para explorar o que a migração envolve. Veja neste tutorial como migrar um aplicativo do App Engine usando o Cloud Datastore para o Cloud Firestore.

Você aprenderá como realizar as seguintes tarefas:

  • Reconhecer as diferenças entre o Datastore e o Firestore
  • Migrar do Cloud Datastore para o Cloud Firestore

O que é necessário

Pesquisa

Como você usará este codelab?

Apenas ler o documento Ler e fazer os exercícios

2. Contexto

O Datastore do App Engine se tornou o próprio produto em 2013, o Google Cloud Datastore, e agora pode ser acessado por desenvolvedores fora do App Engine. No ano seguinte, o Firebase foi adquirido pelo Google. Na época, ele era conhecido pelo banco de dados em tempo real.

Nos anos seguintes, as equipes do Firebase e do Cloud Datastore trabalharam na integração de alguns dos recursos do Firebase no Datastore. Como resultado, em 2017, a próxima geração do Cloud Datastore foi lançada. Para refletir a herança de alguns recursos do Firebase, ele foi renomeado como Cloud Firestore.

O Cloud Firestore se tornou o mecanismo de armazenamento NoSQL padrão para projetos do Google Cloud. Novos aplicativos podem usar o Cloud Firestore de forma nativa, enquanto os bancos de dados do Datastore atuais foram convertidos em segundo plano para o Firestore e agora operam como "Firestore no modo Datastore" para preservar a compatibilidade com as operações do Datastore. Como resultado, os aplicativos só podem operar o Cloud Firestore em um desses modos e, depois de definidos, não podem ser alterados.

Atualmente, quando os usuários criam novos projetos e selecionam uma solução NoSQL, eles precisam selecionar o Firestore no modo Datastore ou o Firestore no modo nativo. Depois que os usuários adicionam entidades do Datastore, eles não podem mudar para o Firestore. Da mesma forma, depois que o modo nativo do Firestore for selecionado, eles não poderão mais voltar para o Datastore (ou para o Firestore no modo Datastore). Para mais detalhes, leia a página Como escolher entre o Cloud Firestore no modo Datastore ou o modo nativo do Firestore. Para migrar um app para o Firestore, é necessário criar um novo projeto, exportar o Datastore e importá-lo para o Firestore. O objetivo deste tutorial é dar aos desenvolvedores uma ideia das diferenças entre o uso do Cloud Datastore e do Cloud Firestore.

Essa migração não é esperada pelos usuários, por isso ela é opcional. Há vantagens óbvias no uso nativo do Cloud Firestore, como autenticação do cliente, integração de regras do Firebase e, é claro, o banco de dados em tempo real do Firebase, mas as etapas de migração são "inconvenientes":

  • Você precisa usar um projeto diferente do atual do seu app.
  • Um projeto em que um app adicionou entidades do Datastore não pode ser alternado para o Firestore em modo nativo
  • Da mesma forma, um projeto que selecionou o Firestore no modo nativo não pode ser revertido para o Firestore no modo Datastore.
  • Não há uma ferramenta de migração que possa transmitir dados de um projeto para outro.
  • Alguns recursos essenciais do Datastore, incluindo namespaces e uma capacidade de gravação maior (> 10 mil/s), não estão disponíveis no Firestore.
  • As ferramentas de exportação e importação são "primitivas" e "tudo ou nada" diferentes.
    • Se o app tiver muitas entidades do Datastore, poderá levar muitas horas para exportar e importar para o Firestore.
    • Durante esse período, seu aplicativo/serviço não poderá gravar/atualizar dados.
    • As atividades de migração contam para o uso normal. pode ser uma boa ideia distribuí-lo (em cotas diárias, se possível) para minimizar os custos.
    • Como o novo serviço é executado em um projeto diferente, você precisará de uma janela para a propagação das atualizações de DNS.
  • O Datastore e o Firestore têm modelos de dados semelhantes, mas diferentes, por isso a migração requer a atualização do funcionamento do app/serviço
    • As consultas de ancestral do Datastore agora são consultas de coleção do Firestore (padrão).
    • As consultas de tipo amplo do Datastore são consultas de grupo de coleções do Firestore
    • Os índices e o tratamento são diferentes etc.

Dito isso, se você tiver um app bastante simples para considerar para migração, se preparando para simular esse tipo de migração ou simplesmente aqui para aprender sobre o Datastore e o Firestore, continue.

Usuários de Python 2:este codelab de migração opcional é apresentado apenas em Python 3. No entanto, como o Cloud Firestore também é compatível com a versão 2.x, os usuários podem interpolar as diferenças de uso. Um exemplo é que os registros do Firestore usam strings Unicode (em vez de strings de bytes). Portanto, um indicador principal u'' é necessário para literais de string Python 2, o que significa que uma função store_visit() 2.x será semelhante a esta:

def store_visit(remote_addr, user_agent):
    doc_ref = fs_client.collection(u'Visit')
    doc_ref.add({
        u'timestamp': datetime.now(),
        u'visitor': u'{}: {}'.format(remote_addr, user_agent),
    })

Fora isso, a biblioteca de cliente deve funcionar de forma semelhante. O único outro problema a considerar é que a biblioteca 2.x do Cloud Firestore está "congelada" no que diz respeito ao desenvolvimento, por isso, recursos cada vez mais novos só vão estar disponíveis na biblioteca de cliente 3.x do Firestore.

Prosseguindo com a migração, estas são as etapas principais deste tutorial:

  1. Configuração/Pré-trabalho
  2. Adicionar a biblioteca do Cloud Firestore
  3. Atualizar arquivos do 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

Recomendamos reutilizar o mesmo projeto usado para concluir o codelab do módulo 3. 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 deste codelab é ter um app de exemplo do Módulo 3 em funcionamento. Se você não tiver um, conclua o tutorial do Módulo 3 (link acima) antes de prosseguir. Caso já esteja familiarizado com o conteúdo, comece com o código do Módulo 3 abaixo.

Não importa se você usa o seu ou o nosso, é no código do Módulo 3 que vamos INICIAR. Este codelab do Módulo 6 orienta você em cada etapa e, quando concluído, deve se parecer com o código no ponto FINISH. Esse tutorial só está disponível para Python 3.

O diretório dos arquivos do Módulo 3 (seus ou nossos) deve ficar assim:

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

3. (Re)implantar o app Módulo 3

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

Requisitos do Python 2

  • Verifique se app.yaml (ainda) faz referência aos pacotes agrupados de terceiros: grpcio e setuptools.
  • Verifique se appengine_config.py ainda usa pkg_resources e google.appengine.ext.vendor para direcionar o app a recursos de terceiros.
  • Na próxima seção, atualizando requirements.txt, você precisa usar google-cloud-firestore==1.9.0, porque essa é a versão final compatível com 2.x da biblioteca de cliente em Python do Firestore.
    • Se o requirements.txt tiver uma entrada para google-cloud-core, deixe-a como está.
    • Exclua lib e reinstale com pip install -t lib -r requirements.txt.

4. Atualizar arquivos de configuração (adicionar a biblioteca do Cloud Firestore)

Depois da configuração, as próximas etapas necessárias são atualizar a configuração e, em seguida, os arquivos do aplicativo. Para o primeiro, a única mudança de configuração é uma pequena troca de pacote no arquivo requirements.txt, então vamos fazer isso agora.

Substitua a linha google-cloud-datastore por google-cloud-firestore em requirements.txt para que ela fique assim:

Flask==1.1.2
google-cloud-firestore==2.0.2

Recomendamos usar as versões mais recentes de cada biblioteca. os números de versão acima são os mais recentes no momento da criação deste artigo. O código na pasta do repositório FINISH é atualizado com mais frequência e pode ter uma versão mais recente.

Não há outras mudanças de configuração, então app.yaml e templates/index.html permanecem como estão.

5. Atualizar arquivos do aplicativo

Há apenas um arquivo de aplicativo, main.py, então todas as alterações nesta seção afetam apenas esse arquivo.

1. Importações

A mudança da importação do pacote é uma pequena alteração de datastore para firestore:

  • Antes:
from google.cloud import datastore
  • Depois:
from google.cloud import firestore

2. Acesso ao Firestore

Depois de inicializar o Flask, crie seu cliente do Firestore. Faça uma mudança semelhante à mostrada acima, mas para a inicialização do cliente:

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

Ao realizar a migração do Cloud NBS para o Cloud Datastore, você já fez o trabalho pesado para chegar ao Cloud Firestore. Com o Datastore, você cria registros de dados na forma de Entidades compostas de propriedades comuns e as agrupa por chaves. Os registros de dados no Firestore são documentos compostos por pares de chave-valor e agrupados em coleções. Migrar do Datastore exige que você pense nessas diferenças porque elas serão concretizadas quando você criar registros de dados e também fizer consultas por eles. Os resultados podem variar dependendo da complexidade do código do Datastore.

No Datastore, as consultas são baseadas no tipo de entidade, além de critérios de filtragem e classificação. Para o Firestore, a consulta de dados é semelhante. Vamos analisar um exemplo rápido, supondo que esses valores de consulta, clientes (ds_client ou fs_client, respectivamente) e importações:

from datetime import datetime
from firestore.Query import DESCENDING

OCT1 = datetime(2020, 10, 1)
LIMIT = 10

Para o Datastore, vamos consultar as dez entidades Visit mais recentes em ordem decrescente de 1o de outubro de 2020:

query = ds_client.query(kind='Visit')
query.add_filter('timestamp', '>=', datetime(2020, 10, 1))
query.order = ['-timestamp']
return query.fetch(limit=LIMIT)

Faça o mesmo para o Firestore com a coleção Visit:

query = fs_client.collection('Visit')
query.where('timestamp', '>=', datetime(2020, 10, 1))
query.order_by('timestamp', direction=DESCENDING)
return query.limit(LIMIT).stream()

A consulta do aplicativo de exemplo é mais simples (sem cláusula "WHERE"). Como revisão, aqui está o código do Cloud Datastore:

  • Antes:
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)

Ao migrar para o Firestore, você vai criar novos documentos semelhantes às entidades e às consultas, conforme mostrado anteriormente.

  • Depois:
def store_visit(remote_addr, user_agent):
    doc_ref = fs_client.collection('Visit')
    doc_ref.add({
        'timestamp': datetime.now(),
        'visitor': '{}: {}'.format(remote_addr, user_agent),
    })

def fetch_visits(limit):
    visits_ref = fs_client.collection('Visit')
    visits = (v.to_dict() for v in visits_ref.order_by('timestamp',
            direction=firestore.Query.DESCENDING).limit(limit).stream())
    return visits

A função principal root() permanece igual ao arquivo de modelo index.html. Revise as alterações, salve, implante e verifique.

6. Resumo/limpeza

Implante o aplicativo

Implante o app novamente com gcloud app deploy e confirme se ele funciona. Seu código deve corresponder ao que está no repositório do módulo 6 (ou uma versão 2.x, se você preferir).

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 a migração opcional do Módulo 6. Essa é provavelmente uma das migrações que podem ser feitas, se não a final, no que diz respeito ao armazenamento de dados do App Engine. Uma migração alternativa é a conteinerização do app para o Cloud Run, caso ainda não tenha feito isso. Consulte os Módulos 4 e 5, codelabs vinculados abaixo.

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 o app estiver desativado, nenhum tráfego será cobrado. No entanto, outra coisa que você pode receber é o uso do Firestore se ele exceder a cota sem custo financeiro. Portanto, 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

Além deste tutorial, há vários outros codelabs de módulos de migração que você pode considerar:

  • 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
    • Essa migração permite que você permaneça 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.
    • Requer que seu app já tenha sido migrado para o Python 3 (o Buildpack não é compatível com o Python 2)

7. 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 3 (START) e Módulo 6 (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 3

(code)

código

Módulo 6

(n/a)

código

Recursos do App Engine

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