1. Visão geral
A série de codelabs da Serverless Migration Station (tutoriais práticos e autoguiados) e os vídeos relacionados têm como objetivo ajudar os desenvolvedores sem servidor do Google Cloud a modernizar os aplicativos orientando-os em uma ou mais migrações, principalmente a migração de serviços legados. Isso torna seus apps mais portáteis e oferece mais opções e flexibilidade, permitindo que você se integre e acesse uma variedade maior de produtos do Cloud e faça upgrade mais fácil para versões de linguagem mais recentes. Embora o foco inicial seja nos 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 em outro lugar, se aplicável.
Neste codelab, você vai aprender a migrar do Blobstore do App Engine para o Cloud Storage. Também há migrações implícitas de:
- framework da Web
webapp2para Flask (abordado no Módulo 1) - NDB do App Engine para NDB do Cloud para acesso ao Datastore (abordado no Módulo 2)
- Python 2 para 3 (o app migrado é compatível com Python 2 e 3)
Consulte os módulos de migração relacionados para mais informações detalhadas.
Você vai aprender a
- Adicionar o uso da API/biblioteca Blobstore do App Engine
- Armazenar uploads de usuários no serviço Blobstore
- Preparar a próxima etapa para migrar para o Cloud Storage
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 de comandos comuns do Linux
- Conhecimento básico sobre desenvolvimento e implantação de apps do App Engine
- Um app do App Engine do módulo 15 funcional: conclua o codelab do módulo 15 (recomendado) ou copie o app do módulo 15 do repositório.
Pesquisa
Como você vai usar este tutorial?
Como você classificaria sua experiência com Python?
Como você classificaria sua experiência de uso dos serviços do Google Cloud?
2. Contexto
Este codelab começa com o app de exemplo do módulo 15 e demonstra como migrar do Blobstore (e NDB) para o Cloud Storage (e Cloud NDB). O processo de migração envolve a substituição de dependências dos serviços legados incluídos do App Engine, o que permite mover seus apps para outra plataforma sem servidor do Cloud ou outra plataforma de hospedagem, se quiser.
Essa migração exige um pouco mais de esforço em comparação com as outras migrações desta série. O Blobstore tem dependências do framework webapp original. Por isso, o app de exemplo usa o framework webapp2 em vez do Flask. Este tutorial apresenta migrações para o Cloud Storage, o Cloud NDB, o Flask e o Python 3.
O app ainda registra "visitas" de usuários finais e mostra as dez mais recentes, mas o codelab anterior (Módulo 15) adicionou uma nova funcionalidade para acomodar o uso do Blobstore: o app pede que os usuários finais façam upload de um artefato (um arquivo) correspondente à "visita". Os usuários podem fazer isso ou selecionar "pular" para recusar. Independente da decisão do usuário, a próxima página renderiza a mesma saída que as versões anteriores do app, mostrando as visitas mais recentes. Outra novidade é que as visitas com artefatos correspondentes têm um link "Visualizar" para mostrar o artefato de uma visita. Este codelab implementa as migrações mencionadas anteriormente, preservando a funcionalidade descrita.
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ê já implantou o app do Módulo 15, 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 se o App Engine está ativado.
2. Receber app de amostra do valor de referência
Um dos pré-requisitos para este codelab é ter um app de exemplo do Módulo 15. Se você não tiver um, acesse a pasta "START" do Módulo 15 (link abaixo). Este codelab orienta você em cada etapa, concluindo com um código semelhante ao da pasta "FINISH" do Módulo 16.
- INICIAR: pasta do módulo 15 (Python 2)
- CONCLUIR: pasta do módulo 16 (Python 2)
- Repositório completo (para clonar ou fazer o download do arquivo ZIP)
O diretório dos arquivos INICIAIS do Módulo 15 deve ter a seguinte aparência:
$ ls README.md app.yaml main-gcs.py main.py templates
O arquivo main-gcs.py é uma versão alternativa de main.py do Módulo 15 que permite a seleção de um bucket do Cloud Storage diferente do padrão de um URL atribuído a um app com base no ID do projeto: PROJECT_ID.appspot.com. Esse arquivo não tem nenhuma função neste codelab (Módulo 16), além de que técnicas de migração semelhantes podem ser aplicadas a ele, se desejado.
3. (Re) Implantar aplicativo de referência
As etapas de pré-trabalho restantes para serem executadas agora:
- Conheça melhor a ferramenta de linha de comando
gcloud - Reimplantar o aplicativo de amostra com
gcloud app deploy - Confirmar se o aplicativo é executado no App Engine sem problemas
Depois de executar essas etapas e confirmar que o app do módulo 15 está funcionando. A página inicial recebe os usuários com um formulário que solicita o upload de um arquivo de artefato de visita e uma opção, um botão "pular", para desativar:

Depois que os usuários fazem upload de um arquivo ou pulam, o app renderiza a página familiar "Visitas mais recentes":

As visitas com um artefato têm um link "Visualizar" à direita do carimbo de data/hora para mostrar (ou baixar) o artefato. Depois de confirmar a funcionalidade do app, você poderá migrar dos serviços legados do App Engine (webapp2, NDB, Blobstore) para alternativas contemporâneas (Flask, Cloud NDB, Cloud Storage).
4. Atualizar os arquivos de configuração
Três arquivos de configuração entram em ação para a versão atualizada do nosso app. As tarefas necessárias são:
- Atualize as bibliotecas integradas de terceiros necessárias em
app.yamle deixe a porta aberta para uma migração do Python 3. - Adicione um
requirements.txt, que especifica todas as bibliotecas necessárias que não são integradas. - Adicione
appengine_config.pypara que o app seja compatível com bibliotecas integradas e de terceiros não integradas.
app.yaml
Edite o arquivo app.yaml atualizando a seção libraries. jinja2 foi removido, e grpcio, setuptools e ssl foram adicionados. Escolha a versão mais recente disponível para todas as três bibliotecas. Adicione também a diretiva runtime do Python 3, mas com um comentário. Quando terminar, ele vai ficar assim (se você selecionou Python 3.9):
ANTES:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: jinja2
version: latest
AFTER:
#runtime: python39
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: grpcio
version: latest
- name: setuptools
version: latest
- name: ssl
version: latest
As mudanças se referem principalmente às bibliotecas integradas do Python 2 disponíveis nos servidores do App Engine (para que você não precise agrupar por conta própria). Removemos o Jinja2 porque ele vem com o Flask, que vamos adicionar ao reqs.txt. Sempre que as bibliotecas de cliente do Google Cloud, como as do Cloud NDB e do Cloud Storage, forem usadas, o grpcio e o setuptools serão necessários. Por fim, o próprio Cloud Storage exige a biblioteca ssl. A diretiva de ambiente de execução comentada na parte de cima é para quando você estiver pronto para portar esse app para o Python 3. Vamos abordar esse assunto no final deste tutorial.
requirements.txt
Adicione um arquivo requirements.txt, exigindo o framework Flask e as bibliotecas de cliente do Cloud NDB e do Cloud Storage, que não são integradas. Crie o arquivo com este conteúdo:
flask
google-cloud-ndb
google-cloud-storage
O ambiente de execução do App Engine para Python 2 exige o autoempacotamento de bibliotecas de terceiros não integradas. Portanto, execute o seguinte comando para instalar essas bibliotecas na pasta "lib":
pip install -t lib -r requirements.txt
Se você tiver o Python 2 e o 3 na sua máquina de desenvolvimento, talvez seja necessário usar o comando pip2 para garantir que as versões do Python 2 dessas bibliotecas sejam obtidas. Depois de fazer upgrade para o Python 3, não é mais necessário fazer o pacote automático.
appengine_config.py
Adicione um arquivo appengine_config.py compatível com bibliotecas de terceiros integradas e não integradas. Crie o arquivo com este conteúdo:
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)
As etapas concluídas agora devem ser semelhantes ou idênticas às listadas na seção Instalar bibliotecas para apps Python 2 da documentação do App Engine. Mais especificamente, o conteúdo de appengine_config.py precisa corresponder ao que está na etapa 5.
O trabalho nos arquivos de configuração foi concluído. Vamos passar para o aplicativo.
5. Modificar arquivos do aplicativo
Importações
O primeiro conjunto de mudanças para main.py inclui a troca de tudo o que está sendo substituído. Confira o que vai mudar:
webapp2é substituído pelo Flask- Em vez de usar o Jinja2 de
webapp2_extras, use o Jinja2 que vem com o Flask. - O Blobstore e o NDB do App Engine são substituídos pelo Cloud NDB e pelo Cloud Storage
- Os gerenciadores do Blobstore em
webappsão substituídos por uma combinação do módulo da biblioteca padrãoio, do Flask e dos utilitárioswerkzeug. - Por padrão, o Blobstore grava em um bucket do Cloud Storage nomeado com base no URL do app (
PROJECT_ID.appspot.com). Como estamos migrando para a biblioteca de cliente do Cloud Storage,google.authé usado para receber o ID do projeto e especificar o mesmo nome de bucket. É possível mudar o nome do bucket, já que ele não está mais codificado.
ANTES:
import webapp2
from webapp2_extras import jinja2
from google.appengine.ext import blobstore, ndb
from google.appengine.ext.webapp import blobstore_handlers
Implemente as mudanças na lista acima substituindo a seção de importação atual em main.py pelo snippet de código abaixo.
AFTER:
import io
from flask import (Flask, abort, redirect, render_template,
request, send_file, url_for)
from werkzeug.utils import secure_filename
import google.auth
from google.cloud import exceptions, ndb, storage
Inicialização e suporte desnecessário ao Jinja2
O próximo bloco de código a ser substituído é o BaseHandler, que especifica o uso do Jinja2 de webapp2_extras. Isso é desnecessário porque o Jinja2 vem com o Flask e é o mecanismo de modelos padrão. Portanto, remova-o.
No lado do Módulo 16, crie instâncias de objetos que não tínhamos no app mais antigo. Isso inclui inicializar o app Flask e criar clientes de API para o Cloud NDB e o Cloud Storage. Por fim, juntamos o nome do bucket do Cloud Storage, conforme descrito acima na seção de importações. Confira as capturas de tela antes e depois da implementação dessas atualizações:
ANTES:
class BaseHandler(webapp2.RequestHandler):
'Derived request handler mixing-in Jinja2 support'
@webapp2.cached_property
def jinja2(self):
return jinja2.get_jinja2(app=self.app)
def render_response(self, _template, **context):
self.response.write(self.jinja2.render_template(_template, **context))
AFTER:
app = Flask(__name__)
ds_client = ndb.Client()
gcs_client = storage.Client()
_, PROJECT_ID = google.auth.default()
BUCKET = '%s.appspot.com' % PROJECT_ID
Atualizar o acesso ao Datastore
O Cloud NDB é quase totalmente compatível com o NDB do App Engine. Uma diferença já abordada é a necessidade de um cliente de API. Outra diferença é que o último exige que o acesso ao Datastore seja controlado pelo gerenciador de contexto Python do cliente de API. Isso significa que todas as chamadas de acesso ao Datastore usando a biblioteca de cliente do Cloud NDB só podem ocorrer em blocos with do Python.
Essa é uma mudança.A outra é que o Blobstore e os objetos dele, por exemplo, BlobKeys, não são compatíveis com o Cloud Storage. Portanto, mude o file_blob para um ndb.StringProperty. Confira abaixo a classe do modelo de dados e as funções store_visit() e fetch_visits() atualizadas que refletem essas mudanças:
ANTES:
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
file_blob = ndb.BlobKeyProperty()
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_blob=upload_key).put()
def fetch_visits(limit):
'get most recent visits'
return Visit.query().order(-Visit.timestamp).fetch(limit)
AFTER:
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
file_blob = ndb.StringProperty()
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_blob=upload_key).put()
def fetch_visits(limit):
'get most recent visits'
with ds_client.context():
return Visit.query().order(-Visit.timestamp).fetch(limit)
Confira uma representação ilustrada das mudanças feitas até agora:

Como atualizar os gerenciadores
Gerenciador de uploads
Os gerenciadores em webapp2 são classes, enquanto no Flask são funções. Em vez de um método de verbo HTTP, o Flask usa o verbo para decorar a função. O Blobstore e os manipuladores webapp são substituídos pela funcionalidade do Cloud Storage, do Flask e dos utilitários dele:
ANTES:
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
'Upload blob (POST) handler'
def post(self):
uploads = self.get_uploads()
blob_id = uploads[0].key() if uploads else None
store_visit(self.request.remote_addr, self.request.user_agent, blob_id)
self.redirect('/', code=307)
AFTER:
@app.route('/upload', methods=['POST'])
def upload():
'Upload blob (POST) handler'
fname = None
upload = request.files.get('file', None)
if upload:
fname = secure_filename(upload.filename)
blob = gcs_client.bucket(BUCKET).blob(fname)
blob.upload_from_file(upload, content_type=upload.content_type)
store_visit(request.remote_addr, request.user_agent, fname)
return redirect(url_for('root'), code=307)
Algumas observações sobre essa atualização:
- Em vez de um
blob_id, os artefatos de arquivo agora são identificados pelo nome do arquivo (fname), se presente, eNonecaso contrário (o usuário desativou o envio de um arquivo). - Os manipuladores do Blobstore abstraíram o processo de upload dos usuários, mas o Cloud Storage não faz isso. Assim, é possível ver o código recém-adicionado que define o objeto blob e o local (bucket) do arquivo, bem como a chamada que realiza o upload real. (
upload_from_file()). - O
webapp2usa uma tabela de roteamento na parte de baixo do arquivo do aplicativo, enquanto as rotas do Flask são encontradas em cada manipulador decorado. - Os dois manipuladores encerram a funcionalidade redirecionando para a página inicial (
/), preservando a solicitaçãoPOSTcom um código de retorno HTTP 307.
Gerenciador de downloads
A atualização do gerenciador de download segue um padrão semelhante ao do gerenciador de upload, mas há muito menos código para analisar. Substitua a funcionalidade do Blobstore e webapp pelos equivalentes do Cloud Storage e do Flask:
ANTES:
class ViewBlobHandler(blobstore_handlers.BlobstoreDownloadHandler):
'view uploaded blob (GET) handler'
def get(self, blob_key):
self.send_blob(blob_key) if blobstore.get(blob_key) else self.error(404)
AFTER:
@app.route('/view/<path:fname>')
def view(fname):
'view uploaded blob (GET) handler'
blob = gcs_client.bucket(BUCKET).blob(fname)
try:
media = blob.download_as_bytes()
except exceptions.NotFound:
abort(404)
return send_file(io.BytesIO(media), mimetype=blob.content_type)
Observações sobre esta atualização:
- Novamente, o Flask decora as funções de gerenciador com a rota delas, enquanto o
webappfaz isso em uma tabela de roteamento na parte de baixo. Portanto, reconheça a sintaxe de correspondência de padrões do último (('/view/([^/]+)?') em comparação com a do Flask ('/view/<path:fname>'). - Assim como no gerenciador de upload, é necessário um pouco mais de trabalho no lado do Cloud Storage para a funcionalidade abstraída pelos gerenciadores do Blobstore, ou seja, identificar o arquivo (blob) em questão e fazer o download explícito do binário em vez da única chamada de método
send_blob()do gerenciador do Blobstore. - Em ambos os casos, um erro HTTP 404 será retornado ao usuário se um artefato não for encontrado.
Gerenciador principal
As mudanças finais no aplicativo principal acontecem no gerenciador principal. Os métodos de verbo HTTP webapp2 são substituídos por uma única função que combina a funcionalidade deles. Substitua a classe MainHandler pela função root() e remova a tabela de roteamento webapp2, conforme mostrado abaixo:
ANTES:
class MainHandler(BaseHandler):
'main application (GET/POST) handler'
def get(self):
self.render_response('index.html',
upload_url=blobstore.create_upload_url('/upload'))
def post(self):
visits = fetch_visits(10)
self.render_response('index.html', visits=visits)
app = webapp2.WSGIApplication([
('/', MainHandler),
('/upload', UploadHandler),
('/view/([^/]+)?', ViewBlobHandler),
], debug=True)
AFTER:
@app.route('/', methods=['GET', 'POST'])
def root():
'main application (GET/POST) handler'
context = {}
if request.method == 'GET':
context['upload_url'] = url_for('upload')
else:
context['visits'] = fetch_visits(10)
return render_template('index.html', **context)
Em vez de métodos get() e post() separados, eles são essencialmente uma instrução if-else em root(). Além disso, como root() é uma única função, há apenas uma chamada para renderizar o modelo para GET e POST, o que não é possível em webapp2.
Confira uma representação ilustrada desse segundo e último conjunto de mudanças no main.py:

(opcional) "Melhoria" da compatibilidade com versões anteriores
Portanto, a solução criada acima funciona perfeitamente, mas apenas se você estiver começando do zero e não tiver arquivos criados pelo Blobstore. Como atualizamos o app para identificar arquivos por nome em vez de BlobKey, o app concluído do Módulo 16 não poderá acessar os arquivos do Blobstore. Em outras palavras, fizemos uma mudança incompatível com versões anteriores ao realizar essa migração. Agora apresentamos uma versão alternativa de main.py chamada main-migrate.py (encontrada no repositório), que tenta preencher essa lacuna.
A primeira "extensão" para oferecer suporte a arquivos criados pelo Blobstore é um modelo de dados que tem um BlobKeyProperty (além de um StringProperty para arquivos criados pelo Cloud Storage):
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
file_blob = ndb.BlobKeyProperty() # backwards-compatibility
file_gcs = ndb.StringProperty()
A propriedade file_blob será usada para identificar arquivos criados no repositório de blobs, enquanto file_gcs é para arquivos do Cloud Storage. Agora, ao criar novas visitas, armazene explicitamente um valor em file_gcs em vez de file_blob. Assim, "store_visit" vai ficar um pouco diferente:
ANTES:
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_blob=upload_key).put()
AFTER:
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_gcs=upload_key).put()
Ao buscar as visitas mais recentes, "normalize" os dados antes de enviá-los ao modelo:
ANTES:
@app.route('/', methods=['GET', 'POST'])
def root():
'main application (GET/POST) handler'
context = {}
if request.method == 'GET':
context['upload_url'] = url_for('upload')
else:
context['visits'] = fetch_visits(10)
return render_template('index.html', **context)
AFTER:
@app.route('/', methods=['GET', 'POST'])
def root():
'main application (GET/POST) handler'
context = {}
if request.method == 'GET':
context['upload_url'] = url_for('upload')
else:
context['visits'] = etl_visits(fetch_visits(10))
return render_template('index.html', **context)
Em seguida, confirme a existência de file_blob ou file_gcs (ou nenhum dos dois). Se houver um arquivo disponível, escolha o que existe e use esse identificador (BlobKey para arquivos criados no Blobstore ou nome do arquivo para arquivos criados no Cloud Storage). Quando dizemos "arquivos criados pelo Cloud Storage", nos referimos a arquivos criados usando a biblioteca de cliente do Cloud Storage. O Blobstore também grava no Cloud Storage, mas, nesse caso, seriam arquivos criados pelo Blobstore.
Agora, o mais importante: o que é essa função etl_visits() usada para normalizar ou ETL (extrair, transformar e carregar) os dados para o usuário final? Esta é a aparência dela:
def etl_visits(visits):
return [{
'visitor': v.visitor,
'timestamp': v.timestamp,
'file_blob': v.file_gcs if hasattr(v, 'file_gcs') \
and v.file_gcs else v.file_blob
} for v in visits]
Provavelmente, ele vai parecer o que você esperava: o código passa por todas as visitas e, para cada uma delas, usa os dados do visitante e do carimbo de data/hora exatamente como estão. Depois, verifica se file_gcs ou file_blob existe e, se sim, escolhe um deles (ou None se nenhum dos dois existir).
Confira uma ilustração das diferenças entre main.py e main-migrate.py:

Se você estiver começando do zero sem arquivos criados pelo Blobstore, use main.py. No entanto, se você estiver fazendo a transição e quiser arquivos de suporte criados pelo Blobstore e pelo Cloud Storage, confira main-migrate.py como um exemplo de como lidar com esse cenário para ajudar você a planejar migrações para seus próprios apps. Ao fazer migrações complexas, é provável que surjam casos especiais. Portanto, este exemplo mostra uma maior afinidade com a modernização de apps reais com dados reais.
6. Resumo/limpeza
Esta seção conclui o codelab implantando o app e verificando se ele funciona conforme o esperado e em qualquer saída refletida. Depois da validação do app, faça as etapas de limpeza e considere as próximas etapas.
Implantar e verificar o aplicativo
Antes de fazer a nova implantação do app, execute pip install -t lib -r requirements.txt para colocar as bibliotecas de terceiros autoempacotadas na pasta "lib". Se quiser executar a solução compatível com versões anteriores, renomeie main-migrate.py como main.py primeiro. Agora, execute gcloud app deploy e confirme se o app funciona de forma idêntica ao app do módulo 15. A tela do formulário é assim:

A página de visitas mais recentes tem esta aparência:

Parabéns por concluir este codelab, substituindo o Blobstore do App Engine pelo Cloud Storage, o NDB do App Engine pelo Cloud NDB e o webapp2 pelo Flask. Agora, seu código precisa corresponder ao que está na pasta FINISH (Módulo 16). A alternativa main-migrate.py também está presente nessa pasta.
"Migração" do Python 3
A diretiva runtime do Python 3 comentada na parte de cima de app.yaml é tudo o que é necessário para portar esse app para o Python 3. O código-fonte já é compatível com o Python 3, então não é necessário fazer mudanças. Para implantar isso como um app Python 3, execute as seguintes etapas:
- Remova o comentário da diretiva
runtimedo Python 3 na parte de cima deapp.yaml. - Exclua todas as outras linhas em
app.yaml. - Exclua o arquivo
appengine_config.py. (não usado no ambiente de execução do Python 3) - Exclua a pasta
lib, se ela existir. (desnecessário com o ambiente de execução do Python 3)
Limpar
Geral
Se você terminou por enquanto, recomendamos que desative o app do App Engine para evitar cobranças. No entanto, se você quiser testar ou experimentar mais, a plataforma do App Engine tem uma cota sem custo financeiro. Portanto, enquanto você não exceder esse nível de uso, não vai receber cobranças. Isso é para computação, mas também pode haver cobranças por serviços relevantes do App Engine. Consulte a página de preços para mais informações. Se essa migração envolver outros serviços do Cloud, eles serão cobrados separadamente. Em qualquer caso, se aplicável, consulte a seção "Específico para este codelab" abaixo.
Para total transparência, a implantação em uma plataforma de computação sem servidor do Google Cloud, como o App Engine, gera custos mínimos de build e armazenamento. O Cloud Build e o Cloud Storage têm cotas sem custo financeiro próprias. O armazenamento dessa imagem usa parte dessa cota. No entanto, talvez você more em uma região que não tem um nível sem custo financeiro. Por isso, fique de olho no uso do armazenamento para minimizar possíveis custos. As "pastas" específicas do Cloud Storage que você precisa analisar incluem:
console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/imagesconsole.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com- Os links de armazenamento acima dependem da sua
PROJECT_IDe *LOC*ação. Por exemplo, "us" se o app estiver hospedado nos EUA.
Por outro lado, se você não quiser continuar com este aplicativo ou outros codelabs de migração relacionados e quiser excluir tudo completamente, desligue seu projeto.
Específico para este codelab
Os serviços listados abaixo são exclusivos deste codelab. Consulte a documentação de cada produto para mais informações:
- O serviço Blobstore do App Engine está sujeito às cotas e limites de dados armazenados. Consulte essa página e a página de preços dos serviços agrupados legados.
- O Cloud Storage tem um nível sem custo financeiro para regiões específicas. Consulte também a página de preços gerais para mais informações.
- O serviço App Engine Datastore é fornecido pelo Cloud Datastore (Cloud Firestore no modo Datastore), que também tem um nível sem custo financeiro. Consulte a página de preços para mais informações."
Se você migrou do módulo 15 para o 16, ainda terá dados no Blobstore. Por isso, incluímos as informações de preços acima.
Próximas etapas
Além deste tutorial, outros módulos de migração que se concentram em migrar dos serviços agrupados legados incluem:
- Módulo 2: migrar do App Engine
ndbpara o Cloud NDB - Módulos 7 a 9: migrar das tarefas push da fila de tarefas do App Engine para o Cloud Tasks
- Módulos 12 e 13: migrar do Memcache do App Engine para o Cloud Memorystore
- Módulos 18 e 19: migrar da fila de tarefas do App Engine (tarefas pull) para o Cloud Pub/Sub
O App Engine não é mais a única plataforma sem servidor no Google Cloud. Se você tem um app pequeno do App Engine ou um com funcionalidade limitada e quer transformá-lo em um microsserviço independente, ou se quer dividir um app monolítico em vários componentes reutilizáveis, esses são bons motivos para considerar a migração para o Cloud Functions. Se a contêinerização se tornou parte do seu fluxo de trabalho de desenvolvimento de aplicativos, principalmente se ele consistir em um pipeline de CI/CD (integração contínua/entrega ou implantação contínua), 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 contentorizar 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.
Independente do módulo de migração que você considerar em seguida, 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 oferece orientações sobre quais migrações considerar e a "ordem" relevante dos módulos de migração.
7. Outros recursos
Problemas/feedback do codelab
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 15 (START) e do Módulo 16 (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 15 | N/A | |
Módulo 16 (este codelab) | (igual ao Python 2) |
Recursos on-line
Confira abaixo recursos on-line que podem ser relevantes para este tutorial:
Blobstore do App Engine e Cloud Storage
- Serviço Blobstore do App Engine
- Migrar para a biblioteca de cliente do Cloud Storage
- Página inicial do Cloud Storage
- Documentação do Cloud Storage
Plataforma do App Engine
- Documentação do App Engine
- Tempo de execução do Python 2 no App Engine (ambiente padrão)
- Como usar bibliotecas integradas do App Engine no App Engine do Python 2
- Tempo de execução do Python 3 no App Engine (ambiente padrão)
- Diferenças entre os ambientes de execução do Python 2 e 3 no App Engine (ambiente padrão)
- Guia de migração do App Engine (ambiente padrão) do Python 2 para o 3
- Informações sobre preços e cotas do App Engine
- Lançamento da plataforma App Engine de segunda geração (2018)
- Comparação entre plataformas de primeira e segunda geração
- Suporte de longo prazo para ambientes de execução legados
- Repositório de exemplos de migração da documentação
- Repositório de exemplos de migração gerado pela comunidade
Outras informações da nuvem
- Python no Google Cloud Platform
- Bibliotecas de cliente do Python para Google Cloud
- Nível "Sempre sem custo financeiro" do Google Cloud
- SDK do Google Cloud (ferramenta de linha de comando
gcloud) - Toda a documentação do Google Cloud
Python
- Sistemas de modelos Django e Jinja2
webapp2framework da Web- Documentação do
webapp2(link em inglês) - Vínculos do
webapp2_extras - Documentação do
webapp2_extrasJinja2 (link em inglês) - Estrutura da Web Flask
Vídeos
- Serverless Migration Station (em inglês)
- Expedições sem servidor
- Inscreva-se no Google Cloud Tech
- Inscreva-se no Google Developers
Licença
Este conteúdo está sob a licença Atribuição 2.0 Genérica da Creative Commons.