1. Descripción general
El objetivo de la serie de codelabs de Serverless Migration Station (instructivos prácticos y de autoaprendizaje) y los videos relacionados es ayudar a los desarrolladores de Google Cloud sin servidores a modernizar sus aplicaciones guiándolos a través de una o más migraciones, principalmente alejándose de los servicios heredados. De esta manera, tus apps serán más portátiles y tendrás más opciones y flexibilidad, lo que te permitirá integrar y acceder a una mayor variedad de productos de Cloud, y actualizarte más fácilmente a versiones de lenguaje más recientes. Si bien, en un principio, se enfoca en los primeros usuarios de Cloud, principalmente los desarrolladores de App Engine (entorno estándar), esta serie es lo suficientemente amplia como para incluir otras plataformas sin servidores, como Cloud Functions y Cloud Run, o en cualquier otro lugar si corresponde.
En este codelab, aprenderás a incluir y usar tareas de extracción de la lista de tareas en cola de App Engine en la app de muestra del codelab del módulo 1. Agregamos su uso de tareas de extracción en este instructivo del módulo 18 y, luego, migramos ese uso a Cloud Pub/Sub en el módulo 19. Quienes usen Task Queues para tareas de envío migrarán a Cloud Tasks y deberán consultar los módulos del 7 al 9.
En un próximo lab,
- Usa la API o el servicio agrupado de App Engine Task Queue
- Agrega el uso de la cola de extracción a una app básica de Flask App Engine NDB de Python 2
Requisitos
- Un proyecto de Google Cloud Platform con una cuenta de facturación activa de GCP
- Habilidades básicas de Python
- Conocimiento práctico de los comandos comunes de Linux
- Conocimientos básicos sobre el desarrollo y la implementación de aplicaciones de App Engine
- Una app de App Engine del módulo 1 en funcionamiento (completa su codelab [recomendado] o copia la app del repo)
Encuesta
¿Cómo usarás este instructivo?
¿Cómo calificarías tu experiencia en Python?
¿Cómo calificarías tu experiencia en el uso de los servicios de Google Cloud?
2. Fondo
Para migrar desde las tareas de extracción de la lista de tareas en cola de App Engine, agrega su uso a la app existente de Flask y App Engine NDB que se generó en el codelab del módulo 1. La app de ejemplo muestra las visitas más recientes al usuario final. Está bien, pero es aún más interesante hacer un seguimiento de los visitantes para ver quiénes son los que más visitan el sitio.
Si bien podríamos usar tareas push para estos recuentos de visitantes, queremos dividir la responsabilidad entre la app de ejemplo, cuyo trabajo es registrar visitas y responder de inmediato a los usuarios, y un "trabajador" designado, cuyo trabajo es registrar los recuentos de visitantes fuera del flujo de trabajo normal de solicitud-respuesta.
Para implementar este diseño, agregaremos el uso de colas de extracción a la aplicación principal y admitiremos la funcionalidad del trabajador. El trabajador puede ejecutarse como un proceso independiente (como una instancia de backend o código que se ejecuta en una VM que siempre está activa), un trabajo cron o una solicitud HTTP básica de línea de comandos con curl o wget. Después de esta integración, podrás migrar la app a Cloud Pub/Sub en el siguiente codelab (módulo 19).
En este instructivo, se incluyen los siguientes pasos:
- Configurar/trabajo previo
- Actualizar configuración
- Modifica el código de la aplicación
3. Configurar/trabajo previo
Esta sección explica cómo:
- Configura el proyecto de Cloud
- Obtén app de ejemplo del modelo de referencia
- (Vuelve a) implementar y validar la app de referencia
Estos pasos garantizan que comiences con código funcional.
1. Configura el proyecto
Si completaste el codelab del módulo 1, vuelve a usar ese mismo proyecto (y el código). De manera alternativa, puedes crear un proyecto nuevo o reutilizar otro proyecto existente. Asegúrate de que el proyecto tenga una cuenta de facturación activa y una app de App Engine habilitada. Busca el ID de tu proyecto, ya que lo necesitarás varias veces en este codelab y lo usarás cada vez que encuentres la variable PROJECT_ID.
2. Obtén app de ejemplo del modelo de referencia
Uno de los requisitos previos para este codelab es tener una app de App Engine del módulo 1 que funcione. Completa el codelab del módulo 1 (recomendado) o copia la app del módulo 1 del repo. Sin importar si usas el tuyo o el nuestro, el código del módulo 1 es el que tendremos en cuenta. Este codelab te guiará en cada paso y concluirá con un código que se parezca al que se encuentra en la carpeta del repositorio del módulo 18 "FINISH".
- INICIO: Carpeta del módulo 1 (Python 2)
- FINALIZAR: Carpeta del módulo 18 (Python 2)
- Repositorio completo (para clonar o descargar el archivo ZIP)
Independientemente de la app del módulo 1 que uses, la carpeta debería verse como el siguiente resultado, posiblemente con una carpeta lib también:
$ ls README.md appengine_config.py requirements.txt app.yaml main.py templates
3. (vuelve a) implementa la aplicación de modelo de referencia
Ejecuta los siguientes pasos para implementar la app del Módulo 1:
- Borra la carpeta
libsi hay una y ejecutapip install -t lib -r requirements.txtpara volver a completarlib. Si tienes instalados Python 2 y 3, es posible que debas usar el comandopip2. - Asegúrate de haber instalado y inicializado la herramienta de línea de comandos de
gcloud, y de haber revisado su uso. - Configura tu proyecto de Cloud con
gcloud config set projectPROJECT_IDsi no quieres ingresar tuPROJECT_IDcon cada comandogcloudque se emita. - Implementa la app de ejemplo con
gcloud app deploy - Confirma que la app del módulo 1 se ejecuta según lo previsto y muestra las visitas más recientes (como se ilustra a continuación).

4. Actualizar configuración
No es necesario realizar cambios en los archivos de configuración estándar de App Engine (app.yaml, requirements.txt, appengine_config.py). En cambio, agrega un nuevo archivo de configuración, queue.yaml, con el siguiente contenido y colócalo en el mismo directorio de nivel superior:
queue:
- name: pullq
mode: pull
El archivo queue.yaml especifica todas las colas de tareas que existen para tu app (excepto la cola default [de envío] que App Engine crea automáticamente). En este caso, solo hay una, una cola de extracción llamada pullq. App Engine requiere que la directiva mode se especifique como pull; de lo contrario, crea una cola de envío de forma predeterminada. Obtén más información para crear colas de extracción en la documentación. Consulta también la página de referencia de queue.yaml para ver otras opciones.
Implementa este archivo por separado de tu app. Seguirás usando gcloud app deploy, pero también proporcionarás queue.yaml en la línea de comandos:
$ 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. Modifica el código de la aplicación
En esta sección, se incluyen actualizaciones de los siguientes archivos:
main.py: Agrega el uso de listas de extracción a la aplicación principal.templates/index.html: Actualiza la plantilla web para mostrar los datos nuevos.
Importaciones y constantes
El primer paso es agregar una nueva importación y varias constantes para admitir las colas de extracción:
- Agrega una importación de la biblioteca de Task Queue,
google.appengine.api.taskqueue. - Agrega tres constantes para admitir el alquiler de la cantidad máxima de tareas de extracción (
TASKS) durante una hora (HOUR) desde nuestra cola de extracción (QUEUE). - Agrega una constante para mostrar las visitas más recientes y los visitantes principales (
LIMIT).
A continuación, se muestra el código original y cómo se ve después de realizar estas actualizaciones:
ANTES:
from flask import Flask, render_template, request
from google.appengine.ext import ndb
app = Flask(__name__)
DESPUÉS:
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__)
Agrega una tarea de extracción (recopila datos para la tarea y crea la tarea en la cola de extracción)
El modelo de datos Visit sigue siendo el mismo, al igual que la consulta de visitas para mostrar en fetch_visits(). El único cambio necesario en esta parte del código se encuentra en store_visit(). Además de registrar la visita, agrega una tarea a la cola de extracción con la dirección IP del visitante para que el trabajador pueda incrementar el 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)
DESPUÉS:
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)
Crea un modelo de datos y una función de consulta para el seguimiento de visitantes
Agrega un modelo de datos VisitorCount para hacer un seguimiento de los visitantes. Debe tener campos para el visitor en sí, así como un número entero counter para hacer un seguimiento de la cantidad de visitas. Luego, agrega una función nueva (o, de manera alternativa, puede ser un classmethod de Python) llamada fetch_counts()para consultar y devolver los principales visitantes en orden de mayor a menor. Agrega la clase y la función justo debajo del cuerpo 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)
Agrega código de trabajador
Agrega una nueva función log_visitors() para registrar a los visitantes a través de una solicitud GET a /log. Utiliza un diccionario o hash para hacer un seguimiento de los recuentos de visitantes más recientes y alquila tantas tareas como sea posible durante una hora. Para cada tarea, se registran todas las visitas del mismo visitante. Con los recuentos en mano, la app actualiza todas las entidades VisitorCount correspondientes que ya están en Datastore o crea nuevas si es necesario. El último paso devuelve un mensaje de texto sin formato que indica cuántos visitantes se registraron a partir de cuántas tareas procesadas. Agrega esta función a main.py justo debajo 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))
Actualiza el controlador principal con los nuevos datos de visualización
Para mostrar los visitantes principales, actualiza el controlador principal root() para invocar fetch_counts(). Además, la plantilla se actualizará para mostrar la cantidad de visitantes principales y las visitas más recientes. Empaqueta los recuentos de visitantes junto con las visitas más recientes de la llamada a fetch_visits() y colócalos en un solo context para pasarlos a la plantilla web. A continuación, se muestra el código antes y después de realizar este cambio:
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)
DESPUÉS:
@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)
Estos son todos los cambios que requiere main.py. A continuación, se muestra una representación gráfica de esas actualizaciones con fines ilustrativos para que tengas una idea general de los cambios que realizarás en main.py:

Actualiza la plantilla web con los nuevos datos de la pantalla
La plantilla web templates/index.html requiere una actualización para mostrar los visitantes principales, además de la carga útil normal de los visitantes más recientes. Coloca los visitantes principales y sus recuentos en una tabla en la parte superior de la página y sigue renderizando las visitas más recientes como antes. El único otro cambio es especificar el número que se muestra a través de la variable limit en lugar de codificarlo de forma rígida. Estas son las actualizaciones que debes realizar en tu plantilla 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>
DESPUÉS:
<!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>
Con esto, se completan los cambios necesarios para agregar el uso de tareas de extracción de la cola de tareas de App Engine a la app de muestra del módulo 1. Tu directorio ahora representa la app de muestra del módulo 18 y debería contener estos archivos:
$ ls README.md appengine_config.py queue.yaml templates app.yaml main.py requirements.txt
6. Resumen/Limpieza
En esta sección, se completa el codelab con la implementación de la app y la verificación de que funcione según lo previsto y en cualquier resultado reflejado. Ejecuta el trabajador por separado para procesar los recuentos de visitantes. Después de la validación de la app, realiza los pasos de limpieza necesarios y considera los próximos pasos.
Implementa y verifica la aplicación
Asegúrate de que ya configuraste tu cola de extracción como lo hicimos cerca de la parte superior de este codelab con gcloud app deploy queue.yaml. Si ya completaste ese paso y tu app de ejemplo está lista para usarse, impleméntala con gcloud app deploy. El resultado debería ser idéntico al de la app del Módulo 1, excepto que ahora incluye una tabla de "visitantes principales" en la parte superior:

Si bien el frontend web actualizado muestra los visitantes principales y las visitas más recientes, ten en cuenta que los recuentos de visitantes no incluyen esta visita. La app muestra los recuentos de visitantes anteriores mientras descarta una nueva tarea que incrementa el recuento de este visitante en la cola de extracción, una tarea que está esperando a ser procesada.
Puedes ejecutar la tarea llamando a /log de varias maneras:
- Un servicio de backend de App Engine
- Un trabajo de
cron - Un navegador web
- Una solicitud HTTP de línea de comandos (
curl,wget, etcétera)
Por ejemplo, si usas curl para enviar una solicitud GET a /log, el resultado se vería de la siguiente manera, dado que proporcionaste tu PROJECT_ID:
$ curl https://PROJECT_ID.appspot.com/log DONE (with 1 task[s] logging 1 visitor[s])
La cantidad actualizada se reflejará en la próxima visita al sitio web. Eso es todo.
Felicitaciones por completar este codelab para agregar el uso del servicio de colas de extracción de App Engine Task Queue a la app de ejemplo correctamente. Ahora está lista para migrar a Cloud Pub/Sub, Cloud NDB y Python 3 en el módulo 19.
Limpia
General
Si terminaste por ahora, te recomendamos que inhabilites tu app de App Engine para evitar incurrir en cargos de facturación. Sin embargo, si deseas realizar más pruebas o experimentos, la plataforma de App Engine tiene una cuota gratuita, por lo que no se te cobrará siempre que no excedas ese nivel de uso. Esto se aplica a la capacidad de procesamiento, pero también puede haber cargos por los servicios relevantes de App Engine, por lo que debes consultar su página de precios para obtener más información. Si esta migración involucra otros servicios de Cloud, estos se facturarán por separado. En cualquier caso, si corresponde, consulta la sección "Específico para este codelab" que se encuentra más abajo.
Para divulgar toda la información, la implementación en una plataforma de computación sin servidores de Google Cloud, como App Engine, genera costos menores de compilación y almacenamiento. Cloud Build tiene su propia cuota gratuita, al igual que Cloud Storage. El almacenamiento de esa imagen usa parte de esa cuota. Sin embargo, es posible que vivas en una región que no tenga ese nivel gratuito, por lo que debes tener en cuenta tu uso de almacenamiento para minimizar los costos potenciales. Las "carpetas" específicas de Cloud Storage que debes revisar incluyen las siguientes:
console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/imagesconsole.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com- Los vínculos de almacenamiento anteriores dependen de tu
PROJECT_IDy *LOC*ación, por ejemplo, "us" si tu app está alojada en EE.UU.
Por otro lado, si no vas a continuar con esta aplicación ni con otros codelabs de migración relacionados y quieres borrar todo por completo, cierra tu proyecto.
Específico para este codelab
Los servicios que se indican a continuación son exclusivos de este codelab. Consulta la documentación de cada producto para obtener más información:
- El servicio de lista de tareas en cola de App Engine no genera ninguna facturación adicional según la página de precios de los servicios heredados incluidos, como la lista de tareas en cola.
- El servicio App Engine Datastore lo proporciona Cloud Datastore (Cloud Firestore en modo Datastore), que también tiene un nivel gratuito. Consulta su página de precios para obtener más información.
Próximos pasos
En esta "migración", agregaste el uso de la cola de envío de Task Queue a la app de muestra del módulo 1, ya que agregaste compatibilidad para hacer un seguimiento de los visitantes y, de este modo, implementaste la app de muestra del módulo 18. En la próxima migración, actualizarás las tareas de extracción de App Engine a Cloud Pub/Sub. Desde fines de 2021, los usuarios ya no están obligados a migrar a Cloud Pub/Sub cuando actualizan a Python 3. Obtén más información sobre este tema en la siguiente sección.
Para migrar a Cloud Pub/Sub, consulta el codelab del módulo 19. Además de eso, hay migraciones adicionales que se deben tener en cuenta, como Cloud Datastore, Cloud Memorystore, Cloud Storage o Cloud Tasks (listas de aplicaciones en cola). También hay migraciones entre productos a Cloud Run y Cloud Functions. Se puede acceder a todo el contenido de Serverless Migration Station (codelabs, videos y código fuente [cuando esté disponible]) en su repositorio de código abierto.
7. Migración a Python 3
En el otoño de 2021, el equipo de App Engine extendió la compatibilidad de muchos de los servicios en paquetes a los entornos de ejecución de segunda generación (que tienen un entorno de ejecución de primera generación). Como resultado, ya no es necesario que migres de servicios agrupados, como App Engine Task Queue, a servicios independientes de Cloud o de terceros, como Cloud Pub/Sub, cuando transfieras tu app a Python 3. En otras palabras, puedes seguir usando Task Queue en las apps de App Engine con Python 3 siempre y cuando adaptes el código para acceder a los servicios agrupados en paquetes desde los entornos de ejecución de próxima generación.
Puedes obtener más información para migrar el uso de los servicios agrupados a Python 3 en el Codelab del módulo 17 y su video correspondiente. Si bien ese tema está fuera del alcance del módulo 18, a continuación se vinculan las versiones de Python 3 de la app del módulo 1 que se transfirieron a Python 3 y que aún usan App Engine NDB. (En algún momento, también estará disponible una versión en Python 3 de la app del módulo 18).
8. Recursos adicionales
A continuación, se enumeran recursos adicionales para los desarrolladores que deseen explorar más a fondo este módulo de migración o uno relacionado, así como los productos relacionados. Esto incluye lugares para proporcionar comentarios sobre este contenido, vínculos al código y varios documentos que pueden resultarte útiles.
Problemas o comentarios de los codelabs
Si encuentras algún problema con este Codelab, primero busca el problema antes de enviarlo. Vínculos para buscar y crear problemas nuevos:
Recursos de migración
En la siguiente tabla, puedes encontrar vínculos a las carpetas del repositorio para el módulo 1 (INICIAR) y el módulo 18 (FINALIZAR). También se puede acceder a ellos desde el repositorio de todas las migraciones de codelab de App Engine. Clónalo o descarga un archivo ZIP.
Codelab | Python 2 | Python 3 |
code (no se incluye en este instructivo) | ||
Módulo 18 (este codelab) | N/A |
Referencias en línea
A continuación, se incluyen recursos pertinentes para este instructivo:
Lista de tareas en cola de App Engine
- Descripción general de la cola de tareas de App Engine
- Descripción general de las colas de extracción de la cola de tareas de App Engine
- Aplicación de ejemplo completa de la cola de extracción de la cola de tareas de App Engine
- Crea colas de extracción de Task Queue
- Video de lanzamiento de la cola de extracción de Google I/O 2011 ( app de ejemplo de Votelator)
- Referencia de
queue.yaml queue.yamlen comparación con Cloud Tasks- Guía de migración de listas de extracción a Pub/Sub
- Muestra de documentación de las listas de extracción de App Engine Task Queue a Cloud Pub/Sub
Plataforma de App Engine
Documentación de App Engine
Tiempo de ejecución de Python 2 App Engine (entorno estándar)
Tiempo de ejecución de Python 3 de App Engine (entorno estándar)
Diferencias entre los entornos de ejecución de Python 2 y 3 de App Engine (entorno estándar)
Guía de migración de Python 2 a 3 de App Engine (entorno estándar)
Información sobre los precios y las cuotas de App Engine
Lanzamiento de la plataforma App Engine de segunda generación (2018)
Asistencia a largo plazo para entornos de ejecución heredados
Ejemplos de migración de documentación
Otra información de la nube
- Python en Google Cloud Platform
- Bibliotecas cliente de Python de Google Cloud
- Nivel "Siempre gratis" de Google Cloud
- SDK de Google Cloud (herramienta de línea de comandos
gcloud) - Toda la documentación de Google Cloud
Videos
- Serverless Migration Station
- Expediciones sin servidores
- Suscríbete a Google Cloud Tech
- Suscríbete a Google Developers
Licencia
Este trabajo cuenta con una licencia Atribución 2.0 Genérica de Creative Commons.