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.
Este codelab ensina como incluir e usar tarefas pull da fila de tarefas do App Engine no app de exemplo do codelab do módulo 1. Vamos adicionar o uso de tarefas de pull neste tutorial do módulo 18 e migrar esse uso para o Cloud Pub/Sub no módulo 19. Quem usa filas de tarefas para tarefas push vai migrar para o Cloud Tasks e precisa consultar os módulos de 7 a 9.
Você vai aprender a
- Usar a API/serviço agrupado da fila de tarefas do App Engine
- Adicionar o uso da fila pull a um app básico do Python 2 Flask App Engine NDB
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 aplicativo do App Engine do Módulo 1 funcional. Conclua o codelab (recomendado) ou copie o app 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
Para migrar das tarefas pull da fila de tarefas do App Engine, adicione o uso delas ao app Flask e App Engine NDB resultante do codelab do módulo 1. O app de exemplo mostra as visitas mais recentes ao usuário final. Isso é bom, mas é ainda mais interessante acompanhar os visitantes para saber quem acessa mais.
Embora possamos usar tarefas de push para essas contagens de visitantes, queremos dividir a responsabilidade entre o app de exemplo, cuja função é registrar visitas e responder imediatamente aos usuários, e um "trabalhador" designado, cuja função é somar as contagens de visitantes fora do fluxo de trabalho normal de solicitação-resposta.
Para implementar esse design, vamos adicionar o uso de filas de extração ao aplicativo principal e oferecer suporte à funcionalidade do worker. O worker pode ser executado como um processo separado (como uma instância de back-end ou um código em execução em uma VM sempre ativa), um cron job ou uma solicitação HTTP básica de linha de comando usando curl ou wget. Depois dessa integração, você poderá migrar o app para o Cloud Pub/Sub no próximo codelab (Módulo 19).
Este tutorial inclui as seguintes etapas:
- Configuração/Pré-trabalho
- Atualizar a configuração
- Modificar o código do aplicativo
3. Configuração/Pré-trabalho
Esta seção explica como:
- Configurar seu projeto do Cloud
- Receber app de amostra do valor de referência
- (Re)Implantar e validar o app de referência
Essas etapas garantem que você esteja começando com um código funcional.
1. Configurar projeto
Se você concluiu o codelab do Módulo 1, reutilize 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 um app do App Engine ativado. Encontre o ID do projeto, porque você vai precisar dele várias vezes neste codelab. Use-o sempre que encontrar a variável PROJECT_ID.
2. Receber app de amostra do valor de referência
Um dos pré-requisitos para este codelab é ter um app do App Engine do Módulo 1 funcionando. Conclua o codelab do Módulo 1 (recomendado) ou copie o app do Módulo 1 do repositório. Independentemente de você usar o nosso ou o seu, o código do Módulo 1 é o que vamos "COMEÇAR". Este codelab orienta você em cada etapa, concluindo com um código semelhante ao que está na pasta do repositório do Módulo 18 "FINISH".
- INICIAR: Pasta do módulo 1 (Python 2)
- CONCLUIR: pasta do módulo 18 (Python 2)
- Repositório completo (para clonar ou fazer o download do arquivo ZIP)
Independente do app do Módulo 1 que você usar, a pasta vai ficar parecida com a saída abaixo, possivelmente com uma pasta lib também:
$ ls README.md appengine_config.py requirements.txt app.yaml main.py templates
3. (Re) Implantar aplicativo de referência
Siga estas etapas para implantar o app do módulo 1:
- Exclua a pasta
libse houver uma e execute:pip install -t lib -r requirements.txtpara preencherlibnovamente. Talvez seja necessário usar o comandopip2se você tiver o Python 2 e o 3 instalados. - Verifique se você instalou e inicializou a ferramenta de linha de comando
gcloude revisou o uso dela. - Defina seu projeto na nuvem com
gcloud config set projectPROJECT_IDse não quiser inserir seuPROJECT_IDcom cada comandogcloudemitido. - Implante o app de exemplo com
gcloud app deploy - Confirme se o app do módulo 1 está funcionando como esperado e mostrando as visitas mais recentes (ilustrado abaixo).

4. Atualizar a configuração
Não é necessário fazer mudanças nos arquivos de configuração padrão do App Engine (app.yaml, requirements.txt, appengine_config.py). Em vez disso, adicione um novo arquivo de configuração, queue.yaml, com o seguinte conteúdo, colocando-o no mesmo diretório de nível superior:
queue:
- name: pullq
mode: pull
O arquivo queue.yaml especifica todas as filas de tarefas que existem para seu app, exceto a fila default (push), que é criada automaticamente pelo App Engine. Neste caso, há apenas uma fila pull chamada pullq. O App Engine exige que a diretiva mode seja especificada como pull. Caso contrário, ele cria uma fila push por padrão. Saiba mais sobre como criar filas pull na documentação. Consulte também a página de referência do queue.yaml para outras opções.
Implante esse arquivo separadamente do app. Você ainda vai usar gcloud app deploy, mas também vai fornecer queue.yaml na linha de comando:
$ gcloud app deploy queue.yaml Configurations to update: descriptor: [/tmp/mod18-gaepull/queue.yaml] type: [task queues] target project: [my-project] WARNING: Caution: You are updating queue configuration. This will override any changes performed using 'gcloud tasks'. More details at https://cloud.google.com/tasks/docs/queue-yaml Do you want to continue (Y/n)? Updating config [queue]...⠹WARNING: We are using the App Engine app location (us-central1) as the default location. Please use the "--location" flag if you want to use a different location. Updating config [queue]...done. Task queues have been updated. Visit the Cloud Platform Console Task Queues page to view your queues and cron jobs. $
5. Modificar o código do aplicativo
Esta seção apresenta atualizações nos seguintes arquivos:
main.py: adicione o uso de filas pull ao aplicativo principal.templates/index.html: atualize o modelo da Web para mostrar os novos dados.
Importações e constantes
A primeira etapa é adicionar uma nova importação e várias constantes para oferecer suporte a filas de extração:
- Adicione uma importação da biblioteca da fila de tarefas,
google.appengine.api.taskqueue. - Adicione três constantes para oferecer suporte à locação do número máximo de tarefas de pull (
TASKS) por uma hora (HOUR) da nossa fila pull (QUEUE). - Adicione uma constante para mostrar as visitas mais recentes e os principais visitantes (
LIMIT).
Confira abaixo o código original e como ele fica após essas atualizações:
ANTES:
from flask import Flask, render_template, request
from google.appengine.ext import ndb
app = Flask(__name__)
AFTER:
from flask import Flask, render_template, request
from google.appengine.api import taskqueue
from google.appengine.ext import ndb
HOUR = 3600
LIMIT = 10
TASKS = 1000
QNAME = 'pullq'
QUEUE = taskqueue.Queue(QNAME)
app = Flask(__name__)
Adicionar uma tarefa de extração (coletar dados para a tarefa e criar uma tarefa na fila pull)
O modelo de dados Visit permanece o mesmo, assim como a consulta de visitas para exibição em fetch_visits(). A única mudança necessária nessa parte do código é em store_visit(). Além de registrar a visita, adicione uma tarefa à fila pull com o endereço IP do visitante para que o worker possa incrementar o contador de visitantes.
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'
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).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)
def store_visit(remote_addr, user_agent):
'create new Visit in Datastore and queue request to bump visitor count'
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
QUEUE.add(taskqueue.Task(payload=remote_addr, method='PULL'))
def fetch_visits(limit):
'get most recent visits'
return Visit.query().order(-Visit.timestamp).fetch(limit)
Criar um modelo de dados e uma função de consulta para o rastreamento de visitantes
Adicione um modelo de dados VisitorCount para rastrear visitantes. Ele precisa ter campos para o visitor e um número inteiro counter para rastrear o número de visitas. Em seguida, adicione uma nova função (ou um classmethod do Python) chamada fetch_counts() para consultar e retornar os principais visitantes em ordem decrescente. Adicione a classe e a função logo abaixo do corpo de fetch_visits():
class VisitorCount(ndb.Model):
visitor = ndb.StringProperty(repeated=False, required=True)
counter = ndb.IntegerProperty()
def fetch_counts(limit):
'get top visitors'
return VisitCount.query().order(-VisitCount.counter).fetch(limit)
Adicionar código do worker
Adicione uma nova função log_visitors() para registrar os visitantes com uma solicitação GET para /log. Ele usa um dicionário/hash para rastrear as contagens de visitantes mais recentes, alugando o máximo de tarefas possível por uma hora. Para cada tarefa, ele totaliza todas as visitas do mesmo visitante. Com as contagens em mãos, o app atualiza todas as entidades VisitorCount correspondentes já no Datastore ou cria novas, se necessário. A última etapa retorna uma mensagem de texto simples indicando quantos visitantes foram registrados e quantas tarefas foram processadas. Adicione esta função a main.py logo abaixo de fetch_counts():
@app.route('/log')
def log_visitors():
'worker processes recent visitor counts and updates them in Datastore'
# tally recent visitor counts from queue then delete those tasks
tallies = {}
tasks = QUEUE.lease_tasks(HOUR, TASKS)
for task in tasks:
visitor = task.payload
tallies[visitor] = tallies.get(visitor, 0) + 1
if tasks:
QUEUE.delete_tasks(tasks)
# increment those counts in Datastore and return
for visitor in tallies:
counter = VisitorCount.query(VisitorCount.visitor == visitor).get()
if not counter:
counter = VisitorCount(visitor=visitor, counter=0)
counter.put()
counter.counter += tallies[visitor]
counter.put()
return 'DONE (with %d task[s] logging %d visitor[s])\r\n' % (
len(tasks), len(tallies))
Atualizar o gerenciador principal com novos dados de exibição
Para mostrar os principais visitantes, atualize o manipulador principal root() para invocar fetch_counts(). Além disso, o modelo será atualizado para mostrar o número de principais visitantes e as visitas mais recentes. Empacote as contagens de visitantes com as visitas mais recentes da chamada para fetch_visits() e coloque isso em um único context para transmitir ao modelo da Web. Confira abaixo o código antes e depois dessa mudança:
ANTES:
@app.route('/')
def root():
'main application (GET) handler'
store_visit(request.remote_addr, request.user_agent)
visits = fetch_visits(10)
return render_template('index.html', visits=visits)
AFTER:
@app.route('/')
def root():
'main application (GET) handler'
store_visit(request.remote_addr, request.user_agent)
context = {
'limit': LIMIT,
'visits': fetch_visits(LIMIT),
'counts': fetch_counts(LIMIT),
}
return render_template('index.html', **context)
Estas são todas as mudanças necessárias em main.py, e aqui está uma representação ilustrativa dessas atualizações para dar uma ideia geral das mudanças que você está fazendo em main.py:

Atualizar o modelo da Web com novos dados de display
O modelo da Web templates/index.html precisa de uma atualização para mostrar os principais visitantes, além da carga normal dos visitantes mais recentes. Solte os principais visitantes e as contagens deles em uma tabela na parte de cima da página e continue renderizando as visitas mais recentes como antes. A única outra mudança é especificar o número mostrado usando a variável limit em vez de codificar o número. Estas são as atualizações que você precisa fazer no modelo da Web:
ANTES:
<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
<body>
<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
<li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>
AFTER:
<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
<body>
<h1>VisitMe example</h1>
<h3>Top {{ limit }} visitors</h3>
<table border=1 cellspacing=0 cellpadding=2>
<tr><th>Visitor</th><th>Visits</th></tr>
{% for count in counts %}
<tr><td>{{ count.visitor|e }}</td><td align="center">{{ count.counter }}</td></tr>
{% endfor %}
</table>
<h3>Last {{ limit }} visits</h3>
<ul>
{% for visit in visits %}
<li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>
Isso conclui as mudanças necessárias para adicionar o uso de tarefas de extração da fila de tarefas do App Engine ao app de exemplo do módulo 1. Seu diretório agora representa o app de exemplo do módulo 18 e deve conter estes arquivos:
$ ls README.md appengine_config.py queue.yaml templates app.yaml main.py requirements.txt
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. Execute o worker separadamente para processar as contagens de visitantes. Depois da validação do app, faça as etapas de limpeza e considere as próximas etapas.
Implantar e verificar o aplicativo
Verifique se você já configurou sua fila pull, como fizemos na parte de cima deste codelab com gcloud app deploy queue.yaml. Se isso já foi feito e o app de exemplo está pronto, implante o app com gcloud app deploy. A saída deve ser idêntica ao app do módulo 1, exceto que agora ela apresenta uma tabela "principais visitantes" na parte de cima:

Embora o front-end da Web atualizado mostre os principais visitantes e as visitas mais recentes, as contagens de visitantes não incluem esta visita. O app mostra as contagens de visitantes anteriores enquanto descarta uma nova tarefa que incrementa a contagem desse visitante na fila pull, uma tarefa que está aguardando processamento.
É possível executar a tarefa chamando /log de várias maneiras:
- Um serviço de back-end do App Engine
- Um
crontrabalho - Um navegador da Web
- Uma solicitação HTTP de linha de comando (
curl,wgetetc.)
Por exemplo, se você usar curl para enviar uma solicitação GET a /log, a saída será semelhante a esta, considerando que você forneceu seu PROJECT_ID:
$ curl https://PROJECT_ID.appspot.com/log DONE (with 1 task[s] logging 1 visitor[s])
A contagem atualizada será refletida na próxima visita ao site. Pronto!
Parabéns por concluir este codelab e adicionar o uso do serviço de fila pull da fila de tarefas do App Engine ao app de exemplo. Agora ele está pronto para migrar para o Cloud Pub/Sub, o Cloud NDB e o Python 3 no Módulo 19.
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 de fila de tarefas do App Engine não gera faturamento adicional de acordo com a página de preços dos serviços agrupados legados, como a fila de tarefas.
- 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.
Próximas etapas
Nessa "migração", você adicionou o uso da fila push da fila de tarefas ao app de exemplo do Módulo 1, adicionando suporte para rastrear visitantes e implementando o app de exemplo do Módulo 18. Na próxima migração, você vai fazer upgrade das tarefas pull do App Engine para o Cloud Pub/Sub. Desde o final de 2021, os usuários não são mais obrigados a migrar para o Cloud Pub/Sub ao fazer upgrade para o Python 3. Leia mais sobre isso na próxima seção.
Para migrar para o Cloud Pub/Sub, consulte o codelab do módulo 19. Além disso, há outras migrações a serem consideradas, como Cloud Datastore, Cloud Memorystore, Cloud Storage ou Cloud Tasks (filas push). Também há migrações entre produtos para o Cloud Run e o Cloud Functions. Todo o conteúdo da Serverless Migration Station (codelabs, vídeos, código-fonte [quando disponível]) pode ser acessado no repositório de código aberto.
7. Migração para o Python 3
No outono de 2021, a equipe do App Engine estendeu o suporte de muitos dos serviços incluídos para ambientes de execução de segunda geração (que têm um ambiente de execução de primeira geração). Como resultado, não é mais necessário migrar de serviços incluídos, como a fila de tarefas do App Engine, para serviços autônomos do Cloud ou de terceiros, como o Cloud Pub/Sub, ao fazer a portabilidade do app para o Python 3. Em outras palavras, você pode continuar usando a fila de tarefas em apps do App Engine em Python 3, desde que faça o refactoring do código para acessar serviços incluídos de ambientes de execução de próxima geração.
Saiba mais sobre como migrar o uso de serviços em pacote para o Python 3 no codelab do módulo 17 e no vídeo correspondente. Embora esse assunto esteja fora do escopo do módulo 18, abaixo estão as versões em Python 3 do app do módulo 1 portadas para Python 3 e ainda usando o App Engine NDB. Em algum momento, uma versão em Python 3 do app do módulo 18 também será disponibilizada.
8. Outros recursos
Confira abaixo mais recursos para desenvolvedores que querem saber mais sobre este ou outros módulos de migração e produtos relacionados. Isso inclui locais para enviar feedback sobre o conteúdo, links para o código e vários documentos que podem ser úteis.
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 1 (START) e do Módulo 18 (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. Clone ou faça o download de um arquivo ZIP.
Codelab | Python 2 | Python 3 |
código (não abordado neste tutorial) | ||
Módulo 18 (este codelab) | N/A |
Referências on-line
Confira abaixo os recursos relevantes para este tutorial:
Filas de tarefas do App Engine
- Visão geral da fila de tarefas do App Engine
- Visão geral das filas de extração da fila de tarefas do App Engine
- App de exemplo completo da fila pull da fila de tarefas do App Engine
- Como criar filas pull da fila de tarefas
- Vídeo de lançamento da fila pull do Google I/O 2011 ( app de exemplo Votelator)
- Referência
queue.yaml queue.yamlx Cloud Tasks- Guia de migração de filas pull para o Pub/Sub
- Exemplo de documentação de filas pull da fila de tarefas do App Engine para o Cloud Pub/Sub
Plataforma do App Engine
Documentação do App Engine
Tempo de execução do Python 2 no App Engine (ambiente padrão)
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)
Suporte de longo prazo para ambientes de execução legados
Exemplos de migração de documentação
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
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.