Migrar um Node.js do Cloud do App Engine para Python 2 e App Cloud Tasks para Python 3 e Cloud Datastore (módulo 9)

1. Visão geral

A série de codelabs da estação de migração sem servidor (tutoriais práticos e individualizados) e os vídeos relacionados têm como objetivo ajudar desenvolvedores sem servidor do Google Cloud a modernizar apps, orientando-os em uma ou mais migrações, principalmente para evitar serviços legados. Isso torna seus apps mais portáteis e oferece mais opções e flexibilidade, o que permite a integração e o acesso a uma variedade maior de produtos do Cloud e o upgrade para versões de idiomas mais recentes com mais facilidade. Embora inicialmente voltada para os 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 outros lugares, se aplicável.

O objetivo deste codelab é fazer a portabilidade do app de exemplo do Módulo 8 para o Python 3, além de mudar o acesso ao Datastore (Cloud Firestore no modo Datastore) do Cloud NBS para a biblioteca de cliente nativa do Cloud Datastore e fazer o upgrade para a versão mais recente da biblioteca de cliente do Cloud Tasks.

Adicionamos o uso da fila de tarefas para tarefas push no Módulo 7 e migramos esse uso para o Cloud Tasks no Módulo 8. Aqui no Módulo 9, vamos falar sobre o Python 3 e o Cloud Datastore. Aqueles que usam filas de tarefas para tarefas pull migrarão para o Cloud Pub/Sub e devem consultar os módulos 18 a 19.

Você vai aprender a

  • Transferir o app de exemplo do módulo 8 para o Python 3
  • Alternar o acesso ao Datastore do Cloud NBS para as bibliotecas de cliente do Cloud Datastore
  • Fazer upgrade para a versão mais recente da biblioteca de cliente do Cloud Tasks

O que é necessário

Pesquisa

Como você usará este tutorial?

Apenas ler o documento Ler e fazer os exercícios

Como você classificaria sua experiência com Python?

Iniciante Intermediário Proficiente

Como você classificaria sua experiência de uso dos serviços do Google Cloud?

Iniciante Intermediário Proficiente

2. Contexto

O módulo 7 demonstra como usar as tarefas push da fila de tarefas do App Engine em aplicativos Python 2 Flask do App Engine. No módulo 8, você vai migrar esse app da fila de tarefas para o Cloud Tasks. Aqui no módulo 9, você continua essa jornada e transfere esse aplicativo para o Python 3, além de mudar o acesso ao Datastore de usar o Cloud NBS para a biblioteca de cliente nativa do Cloud Datastore.

Como o Cloud NBS funciona com Python 2 e 3, ele é suficiente para usuários do App Engine que estejam migrando aplicativos do Python 2 para o 3. Uma migração adicional de bibliotecas de cliente para o Cloud Datastore é totalmente opcional, e há apenas um motivo para considerá-la: você tem aplicativos que não são do App Engine (e/ou aplicativos Python 3 do App Engine) já usando a biblioteca de cliente do Cloud Datastore e quer consolidar sua base de código para acessar o Datastore com apenas uma biblioteca de cliente. O Cloud NBS foi criado especificamente para desenvolvedores do App Engine em Python 2 como uma ferramenta de migração do Python 3. Portanto, se você ainda não tem um código que usa a biblioteca de cliente do Cloud Datastore, não precisa considerar essa migração.

Por fim, o desenvolvimento da biblioteca de cliente do Cloud Tasks continua somente no Python 3, por isso estamos "migrando" de uma das versões finais do Python 2 para a contemporânea do Python 3. Felizmente, não há alterações interruptivas no Python 2, o que significa que não é preciso fazer mais nada.

Este tutorial apresenta as seguintes etapas:

  1. Configuração/Pré-trabalho
  2. Atualizar a configuração
  3. Modificar o código do aplicativo

3. Configuração/Pré-trabalho

Esta seção explica como:

  1. Configurar seu projeto do Cloud
  2. Receber app de amostra do valor de referência
  3. (Re)implantar e validar o app de referência

Essas etapas garantem que você esteja começando com o código em funcionamento e que ele esteja pronto para a migração para os serviços do Cloud.

1. Configurar projeto

Se você concluiu o codelab do módulo 8, reutilize o mesmo projeto e código. Outra opção é criar um novo projeto ou reutilizar um projeto existente. Verifique se o projeto tem uma conta de faturamento ativa e um aplicativo do App Engine ativado. Use o ID do projeto sempre que encontrar a variável PROJECT_ID. Ele precisa estar à mão durante este codelab.

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

Um dos pré-requisitos é um app funcional do Módulo 8 do App Engine: conclua o codelab do Módulo 8 (recomendado) ou copie o app do Módulo 8 do repositório. Não importa se você usa o seu ou o nosso, o código do Módulo 8 é por onde começaremos ("INICIAR"). Este codelab orienta você durante a migração, concluindo com um código semelhante ao que está na pasta de repositório do Módulo 9 ("FINISH").

Independentemente do app do Módulo 7 que você usar, a pasta será semelhante à mostrada abaixo, possivelmente também com uma pasta lib:

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

3. (Re)implantar e validar o app de referência

Execute as etapas a seguir para implantar o app Module 8:

  1. Exclua a pasta lib, se houver uma, e execute pip install -t lib -r requirements.txt para preencher lib novamente. Pode ser necessário usar pip2 se você tiver o Python 2 e o 3 instalados na sua máquina de desenvolvimento.
  2. Verifique se você instalou e inicializou a ferramenta de linha de comando gcloud e analisou o uso dela.
  3. (Opcional) Defina o projeto do Cloud com gcloud config set project PROJECT_ID se você não quiser inserir PROJECT_ID em cada comando gcloud emitido.
  4. Implante o app de exemplo com gcloud app deploy
  5. Confirme se o app é executado como esperado sem problemas. Se você concluiu o codelab do Módulo 8, o app vai mostrar os principais visitantes junto com as visitas mais recentes (ilustrados abaixo). Na parte de baixo, há uma indicação das tarefas mais antigas que serão excluídas.

4aa8a2cb5f527079.png

4. Atualizar a configuração

requirements.txt

O novo requirements.txt é quase igual ao do Módulo 8, com apenas uma grande mudança: substitua google-cloud-ndb por google-cloud-datastore. Faça essa mudança para que o arquivo requirements.txt fique assim:

flask
google-cloud-datastore
google-cloud-tasks

Este arquivo requirements.txt não tem números de versão, o que significa que as versões mais recentes foram selecionadas. Se surgir alguma incompatibilidade, o uso de números de versão para fixar versões de trabalho de um app é uma prática padrão.

app.yaml

O ambiente de execução do App Engine de segunda geração não oferece suporte a bibliotecas de terceiros integradas, como a versão 2.x, nem à 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.

Outra atualização é que o ambiente de execução do Python 3 exige o uso de frameworks da Web com roteamento próprio. Como resultado, todos os gerenciadores de script precisam ser alterados para auto. No entanto, como todas as rotas precisam ser alteradas para auto e não há arquivos estáticos exibidos por esse app de exemplo, é irrelevante ter qualquer gerenciador. Portanto, remova também toda a seção handlers.

A única coisa necessária em app.yaml é definir o ambiente de execução como uma versão compatível do Python 3, por exemplo, 3.10. Faça essa mudança para que o novo app.yaml (abreviado) seja apenas esta linha:

runtime: python310

Excluir appengine_config.py e lib

Os ambientes de execução de última geração do App Engine reformulam o uso de pacotes de terceiros:

  • As bibliotecas integradas são aquelas verificadas pelo Google e disponibilizadas nos servidores do App Engine, provavelmente porque contêm código C/C++ que os desenvolvedores não têm permissão para implantar na nuvem. Elas não estão mais disponíveis nos ambientes de execução de segunda geração.
  • Não é mais necessário copiar bibliotecas não integradas (às vezes chamadas de "fornecimento" ou "autoagrupamento") em ambientes de execução de segunda geração. Em vez disso, elas precisam estar listadas em requirements.txt, em que o sistema de build as instala automaticamente em seu nome no momento da implantação.

Como resultado dessas mudanças no gerenciamento de pacotes de terceiros, o arquivo appengine_config.py e a pasta lib não são necessários. Portanto, exclua-os. Nos ambientes de execução de segunda geração, o App Engine instala automaticamente pacotes de terceiros listados em requirements.txt. Resumindo:

  1. Sem bibliotecas de terceiros copiadas ou agrupadas. liste-os 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. Não há uma lista de bibliotecas integradas de terceiros (sem a seção libraries) no app.yaml. listá-los em requirements.txt
  4. Não há bibliotecas de terceiros para referenciar no app, o que significa que não há um arquivo appengine_config.py

O único requisito para desenvolvedores é listar todas as bibliotecas de terceiros no requirements.txt.

5. Atualizar arquivos do aplicativo

Como há apenas um arquivo de aplicativo, main.py, todas as mudanças feitas na seção afetam apenas esse arquivo. Abaixo há uma "diferença" ilustração sobre as mudanças gerais que precisam ser feitas para refatorar o código existente no novo app. Os leitores não devem ler o código linha por linha, porque o objetivo é simplesmente ter uma visão geral pictórica do que é necessário nessa refatoração. Fique à vontade para abrir em uma nova guia ou fazer o download e aumentar o zoom, se quiser.

5d043768ba7be742.png

Atualizar importações e inicialização

A seção de importação em main.py para o Módulo 8 usa o Cloud NFS e o Cloud Tasks. ele será semelhante a este:

ANTES:

from datetime import datetime
import json
import logging
import time
from flask import Flask, render_template, request
import google.auth
from google.cloud import ndb, tasks

app = Flask(__name__)
ds_client = ndb.Client()
ts_client = tasks.CloudTasksClient()

A geração de registros foi simplificada e aprimorada nos ambientes de execução de segunda geração, como Python 3:

  • Para ter uma experiência abrangente de geração de registros, use o Cloud Logging.
  • Para simplificar a geração de registros, basta enviar para stdout (ou stderr) via print()
  • Não é necessário usar o módulo logging do Python. Portanto, remova-o.

Dessa forma, exclua a importação de logging e troque google.cloud.ndb por google.cloud.datastore. Da mesma forma, altere ds_client para apontar para um cliente Datastore em vez de um cliente RDP. Com essas mudanças, a parte de cima do novo app vai ficar assim:

DEPOIS:

from datetime import datetime
import json
import time
from flask import Flask, render_template, request
import google.auth
from google.cloud import datastore, tasks

app = Flask(__name__)
ds_client = datastore.Client()
ts_client = tasks.CloudTasksClient()

Migrar para o Cloud Datastore

Agora é hora de substituir o uso da biblioteca de cliente do NBS pelo Datastore. Tanto o App Engine MapReduce quanto o Cloud Node exigem um modelo de dados (classe). para este app, é Visit. A função store_visit() funciona da mesma forma em todos os outros módulos de migração: ela registra uma visita criando um novo registro Visit, salvando o endereço IP e o user agent de um cliente visitante (tipo de navegador).

ANTES:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)

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

No entanto, o Cloud Datastore não usa uma classe de modelo de dados, portanto, exclua essa classe. Além disso, o Cloud Datastore não cria automaticamente um carimbo de data/hora quando os registros são criados, exigindo que você faça isso manualmente. Isso é feito com a chamada datetime.now().

Sem a classe de dados, o store_visit() modificado ficará assim:

DEPOIS:

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

A principal função é fetch_visits(). Ele não apenas executa a consulta original para as Visits mais recentes, mas também pega o carimbo de data/hora das últimas Visit exibidas e cria a tarefa push que chama /trim (portanto, trim()) para excluir em massa as Visits antigas. Aqui ele está usando o Cloud NBS:

ANTES:

def fetch_visits(limit):
    'get most recent visits & add task to delete older visits'
    with ds_client.context():
        data = Visit.query().order(-Visit.timestamp).fetch(limit)
    oldest = time.mktime(data[-1].timestamp.timetuple())
    oldest_str = time.ctime(oldest)
    logging.info('Delete entities older than %s' % oldest_str)
    task = {
        'app_engine_http_request': {
            'relative_uri': '/trim',
            'body': json.dumps({'oldest': oldest}).encode(),
            'headers': {
                'Content-Type': 'application/json',
            },
        }
    }
    ts_client.create_task(parent=QUEUE_PATH, task=task)
    return (v.to_dict() for v in data), oldest_str

As principais mudanças:

  1. Troque a consulta do Cloud NBS pelo equivalente do Cloud Datastore. os estilos de consulta diferem um pouco.
  2. O Datastore não requer o uso de um gerenciador de contexto nem faz com que você extraia os dados (com to_dict()) da mesma forma que o Cloud Firestore.
  3. Substituir chamadas de geração de registros por print()

Depois dessas mudanças, o fetch_visits() vai ficar assim:

DEPOIS:

def fetch_visits(limit):
    'get most recent visits & add task to delete older visits'
    query = ds_client.query(kind='Visit')
    query.order = ['-timestamp']
    visits = list(query.fetch(limit=limit))
    oldest = time.mktime(visits[-1]['timestamp'].timetuple())
    oldest_str = time.ctime(oldest)
    print('Delete entities older than %s' % oldest_str)
    task = {
        'app_engine_http_request': {
            'relative_uri': '/trim',
            'body': json.dumps({'oldest': oldest}).encode(),
            'headers': {
                'Content-Type': 'application/json',
            },
        }
    }
    ts_client.create_task(parent=QUEUE_PATH, task=task)
    return visits, oldest_str

Isso normalmente seria tudo o que é necessário. Infelizmente, há um problema importante.

(Possivelmente) Criar uma nova fila (push)

No Módulo 7, adicionamos o uso do App Engine taskqueue ao app do Módulo 1. Um benefício-chave de ter tarefas push como um recurso legado do App Engine é que um "padrão" é criada automaticamente. Quando esse app foi migrado para o Cloud Tasks no módulo 8, essa fila padrão já estava lá. Por isso, ainda não precisamos nos preocupar com isso. Isso muda aqui no Módulo 9.

Um aspecto crítico a ser considerado é que o novo aplicativo do App Engine não usa mais os serviços do App Engine e, por isso, não é mais possível presumir que o App Engine cria automaticamente uma fila de tarefas automaticamente em um produto diferente (Cloud Tasks). Conforme escrito, a criação de uma tarefa em fetch_visits() (para uma fila inexistente) falhará. Uma nova função é necessária para verificar se a fila ("padrão") existe. Caso não exista uma, crie uma.

Chame esta função _create_queue_if() e a adicione ao seu aplicativo logo acima de fetch_visits(), porque é onde ela é chamada. O corpo da função a ser adicionada:

def _create_queue_if():
    'app-internal function creating default queue if it does not exist'
    try:
        ts_client.get_queue(name=QUEUE_PATH)
    except Exception as e:
        if 'does not exist' in str(e):
            ts_client.create_queue(parent=PATH_PREFIX,
                    queue={'name': QUEUE_PATH})
    return True

A função create_queue() do Cloud Tasks requer o nome completo do caminho da fila, exceto o nome da fila. Para simplificar, crie outra variável PATH_PREFIX que represente o QUEUE_PATH menos o nome da fila (QUEUE_PATH.rsplit('/', 2)[0]). Adicione a definição perto do topo para que o bloco de código com todas as atribuições de constantes fique assim:

_, PROJECT_ID = google.auth.default()
REGION_ID = 'REGION_ID'    # replace w/your own
QUEUE_NAME = 'default'     # replace w/your own
QUEUE_PATH = ts_client.queue_path(PROJECT_ID, REGION_ID, QUEUE_NAME)
PATH_PREFIX = QUEUE_PATH.rsplit('/', 2)[0]

Agora modifique a última linha em fetch_visits() para usar _create_queue_if(). Primeiro, crie a fila, se necessário, e depois crie a tarefa:

    if _create_queue_if():
        ts_client.create_task(parent=QUEUE_PATH, task=task)
    return visits, oldest_str

Agora, _create_queue_if() e fetch_visits() ficarão assim agregados:

def _create_queue_if():
    'app-internal function creating default queue if it does not exist'
    try:
        ts_client.get_queue(name=QUEUE_PATH)
    except Exception as e:
        if 'does not exist' in str(e):
            ts_client.create_queue(parent=PATH_PREFIX,
                    queue={'name': QUEUE_PATH})
    return True

def fetch_visits(limit):
    'get most recent visits & add task to delete older visits'
    query = ds_client.query(kind='Visit')
    query.order = ['-timestamp']
    visits = list(query.fetch(limit=limit))
    oldest = time.mktime(visits[-1]['timestamp'].timetuple())
    oldest_str = time.ctime(oldest)
    print('Delete entities older than %s' % oldest_str)
    task = {
        'app_engine_http_request': {
            'relative_uri': '/trim',
            'body': json.dumps({'oldest': oldest}).encode(),
            'headers': {
                'Content-Type': 'application/json',
            },
        }
    }
    if _create_queue_if():
        ts_client.create_task(parent=QUEUE_PATH, task=task)
    return visits, oldest_str

Além da necessidade de adicionar esse código extra, o restante do código do Cloud Tasks permanece praticamente intacto desde o Módulo 8. A parte final do código a observar é o gerenciador de tarefas.

Atualizar o gerenciador de tarefas (push)

No gerenciador de tarefas, trim(), o código do Cloud NBS consulta visitas mais antigas que as mais antigas exibidas. Ele usa uma consulta somente de chaves para agilizar as coisas. Por que buscar todos os dados se você só precisa dos IDs de visitas? Depois de ter todos os IDs de visita, exclua-os em um lote com a função delete_multi() do Cloud NBS.

ANTES:

@app.route('/trim', methods=['POST'])
def trim():
    '(push) task queue handler to delete oldest visits'
    oldest = float(request.get_json().get('oldest'))
    with ds_client.context():
        keys = Visit.query(
                Visit.timestamp < datetime.fromtimestamp(oldest)
        ).fetch(keys_only=True)
        nkeys = len(keys)
        if nkeys:
            logging.info('Deleting %d entities: %s' % (
                    nkeys, ', '.join(str(k.id()) for k in keys)))
            ndb.delete_multi(keys)
        else:
            logging.info(
                    'No entities older than: %s' % time.ctime(oldest))
    return ''   # need to return SOME string w/200

Assim como fetch_visits(), a maior parte das mudanças envolve a troca do código do Cloud NBS para o Cloud Datastore, o ajuste dos estilos de consulta, a remoção do uso do gerenciador de contexto e a alteração das chamadas de geração de registros para print().

DEPOIS:

@app.route('/trim', methods=['POST'])
def trim():
    '(push) task queue handler to delete oldest visits'
    oldest = float(request.get_json().get('oldest'))
    query = ds_client.query(kind='Visit')
    query.add_filter('timestamp', '<', datetime.fromtimestamp(oldest))
    query.keys_only()
    keys = list(visit.key for visit in query.fetch())
    nkeys = len(keys)
    if nkeys:
        print('Deleting %d entities: %s' % (
                nkeys, ', '.join(str(k.id) for k in keys)))
        ds_client.delete_multi(keys)
    else:
        print('No entities older than: %s' % time.ctime(oldest))
    return ''   # need to return SOME string w/200

Não há mudanças no gerenciador principal do aplicativo root().

Porta para Python 3

Este aplicativo de exemplo foi projetado para ser executado em Python 2 e 3. Todas as alterações específicas do Python 3 foram abordadas anteriormente em seções relevantes deste tutorial. Não são necessárias etapas adicionais nem bibliotecas de compatibilidade.

Atualização do Cloud Tasks

A versão final da biblioteca de cliente do Cloud Tasks com suporte ao Python 2 é a 1.5.0. No momento em que este artigo foi escrito, a versão mais recente da biblioteca de cliente para Python 3 era totalmente compatível com essa versão. Portanto, nenhuma outra atualização é necessária.

Atualização do modelo HTML

Nenhuma mudança é necessária no arquivo de modelo HTML templates/index.html. Isso encerra todas as mudanças necessárias para chegar ao app Módulo 9.

6. Resumo/limpeza

Implante e verifique o aplicativo

Depois de concluir as atualizações do código, principalmente a porta para Python 3, implante o app com gcloud app deploy. A saída deve ser idêntica aos aplicativos dos módulos 7 e 8, exceto pelo fato de você ter movido o acesso do banco de dados para a biblioteca de cliente do Cloud Datastore e feito upgrade para o Python 3:

App visitme do módulo 7

Esta etapa conclui o codelab. Convidamos você a comparar seu código com o que está na pasta do módulo 9. Parabéns!

Limpar

Geral

Se você já tiver terminado por enquanto, recomendamos que desative seu aplicativo do App Engine para evitar cobranças. No entanto, se você quiser fazer mais testes, saiba que a plataforma do App Engine tem uma cota sem custo financeiro e, desde que você não exceda esse nível de uso, não haverá cobranças. Isso é para computação, mas também pode haver cobranças por serviços relevantes do App Engine. Portanto, consulte a página de preços para mais informações. Se essa migração envolver outros serviços do Cloud, eles serão faturados separadamente. Em ambos os casos, se aplicável, consulte a seção "Específico para este codelab". seção abaixo.

Para divulgação completa, a implantação em uma plataforma de computação sem servidor do Google Cloud, como o App Engine, incorre em menores custos de criação e armazenamento. O Cloud Build tem a própria cota sem custo financeiro, assim como o Cloud Storage. O armazenamento da imagem consome parte da cota. No entanto, talvez você more em uma região que não tenha esse nível sem custo financeiro, portanto, esteja ciente do uso do armazenamento para minimizar os possíveis custos. "Pastas" específicas do Cloud Storage que você deve analisar incluem:

  • console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/images
  • console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com
  • Os links de armazenamento acima dependem do PROJECT_ID e da *LOC*ação, por exemplo, "us" caso seu app esteja hospedado nos EUA.

Por outro lado, se você não for continuar com este aplicativo ou outros codelabs de migração relacionados e quiser excluir tudo completamente, encerre seu projeto.

Específicos deste codelab

Os serviços listados abaixo são exclusivos deste codelab. Consulte a documentação de cada produto para mais informações:

Próximas etapas

Isso conclui nossa migração das tarefas push da Fila de tarefas do App Engine para o Cloud Tasks. A migração opcional do Cloud NBS para o Cloud Datastore também é abordada por conta própria (sem a fila de tarefas ou o Cloud Tasks) no Módulo 3. Além do Módulo 3, existem outros módulos de migração com foco na mudança dos serviços em pacote legados do App Engine que devem ser considerados:

  • Módulo 2: migrar do App Engine MapReduce para o Cloud NBS
  • Módulo 3: migrar do Cloud Firestore para o Cloud Datastore
  • Módulos 12 a 13: migrar do Memcache do App Engine para o Cloud Memorystore
  • Módulos 15 a 16: migrar do App Engine Blobstore para o Cloud Storage
  • Módulos 18 a 19: fila de tarefas do App Engine (tarefas pull) para o Cloud Pub/Sub

O App Engine não é mais a única plataforma sem servidor do Google Cloud. Se você tem um aplicativo pequeno do App Engine ou com funcionalidade limitada e quer transformá-lo em um microsserviço independente ou quer dividir um aplicativo monolítico em vários componentes reutilizáveis, estes são bons motivos para migrar para o Cloud Functions. Se a conteinerização se tornou parte do fluxo de trabalho de desenvolvimento de aplicativos, principalmente se consistir em um pipeline de CI/CD (integração/entrega contínua ou implantação), 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 conteinerizar 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.

Seja qual for o módulo de migração que você considerar a seguir, 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 fornece orientações sobre quais migrações considerar e qualquer "ordem" relevante. de módulos de migração.

7. Outros recursos

Problemas/feedback sobre 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 8 (INÍCIO) e do Módulo 9 (FINISH) podem ser encontrados na tabela abaixo. Eles também podem ser acessados no repositório de todas as migrações de codelab do App Engine. Você pode clonar ou fazer o download de um arquivo ZIP.

Codelab

Python 2

Python 3

Módulo 8

código

(n/a)

Módulo 9

(n/a)

código

Recursos on-line

Veja abaixo recursos on-line que podem ser relevantes para este tutorial:

App Engine

Cloud NDB

Cloud Datastore

Cloud Tasks

Outras informações sobre a nuvem

Licença

Este conteúdo está sob a licença Atribuição 2.0 Genérica da Creative Commons.