1. Descripción general
La serie de codelabs Serverless Migration Station (instructivos prácticos y autoaprendizaje) y los videos relacionados tienen como objetivo ayudar a los desarrolladores de Google Cloud sin servidores a modernizar sus apps guiándolos a través de una o más migraciones, en especial al alejarse 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á integrarlas con una variedad más amplia de productos de Cloud y acceder a ella, y actualizar con mayor facilidad a versiones de idiomas más recientes. Aunque inicialmente 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 cualquier otra, 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 ejemplo 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 más adelante en el módulo 19. Aquellos que usen listas de tareas en cola para tareas push migrarán a Cloud Tasks en su lugar, por lo que deberán consultar los módulos 7-9.
En un próximo lab,
- Usa la API o el servicio empaquetado de la lista de tareas en cola de App Engine
- Agrega el uso de la lista de extracción a una app básica de Flask en App Engine NDB de Python 2.
Requisitos
- Un proyecto de Google Cloud Platform con una cuenta de facturación de GCP activa
- 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 que funcione (completa su codelab [recomendado] o copia la app del repositorio)
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. Información general
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 NBS que resulta del codelab del módulo 1. La app de ejemplo muestra las visitas más recientes al usuario final. No hay problema, pero es más interesante también hacer un seguimiento de los visitantes para ver quiénes tienen más visitas.
Si bien podríamos usar push Tasks 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 contabilizar los recuentos de visitantes fuera del flujo de trabajo normal de solicitud-respuesta.
Para implementar este diseño, agregaremos el uso de listas de extracción a la aplicación principal y admitiremos la funcionalidad del trabajador. El trabajador puede ejecutarse como un proceso separado (como una instancia de backend o un 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 muestran 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
- (Re)Implementa y valida la app de referencia
Con estos pasos, te aseguras de comenzar a trabajar con código.
1. Configura el proyecto
Si completaste el codelab del módulo 1, vuelve a usar ese mismo proyecto (y código). Como alternativa, crea un proyecto completamente nuevo o reutiliza otro proyecto existente. Asegúrate de que el proyecto tenga una cuenta de facturación activa y una app de App Engine habilitada. Encuentra tu ID del proyecto, ya que lo necesitarás varias veces en este codelab y úsalo cuando 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 repositorio. Ya sea que uses el tuyo o el nuestro, comenzaremos en el código del módulo 1. En este codelab, se explica cada paso y se concluye con un código similar al que se encuentra en la carpeta del repositorio del módulo 18, “FINISH”.
- INICIO: Carpeta del módulo 1 (Python 2)
- FIN: Carpeta del módulo 18 (Python 2)
- Repositorio completo (para clonar o descargar un archivo ZIP)
Independientemente de la app del Módulo 1 que uses, la carpeta debería verse como el resultado a continuación, posiblemente con una carpeta lib
:
$ 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
lib
si hay una y ejecutapip install -t lib -r requirements.txt
para volver a propagarlib
. Es posible que debas usar el comandopip2
en su lugar si tienes instalados Python 2 y 3. - Asegúrate de haber instalado e 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 project
PROJECT_ID
si no quieres ingresar tuPROJECT_ID
con cada comandogcloud
emitido. - Implementa la app de ejemplo con
gcloud app deploy
- Confirma que la app del Módulo 1 se ejecute según lo esperado y muestre 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 su lugar, 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 listas de tareas en cola que existen para tu app (excepto la lista de aplicaciones en cola default
, que App Engine crea automáticamente). En este caso, solo hay una, una lista de extracción llamada pullq
. App Engine requiere que la directiva mode
se especifique como pull
; de lo contrario, crea una lista de aplicaciones en cola de forma predeterminada. Obtén más información sobre cómo crear listas 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 importación nueva y varias constantes para admitir listas de extracción:
- Agrega una importación de la biblioteca de lista de tareas en cola,
google.appengine.api.taskqueue
. - Agrega tres constantes para admitir liberar la cantidad máxima de tareas de extracción (
TASKS
) durante una hora (HOUR
) desde nuestra lista de extracción (QUEUE
). - Agregar 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 verá 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__)
Agregar una tarea de extracción (recopilar datos para la tarea y crear una tarea en la lista de extracción)
El modelo de datos Visit
sigue siendo el mismo, al igual que las consultas de visitas para mostrar en fetch_visits()
. El único cambio necesario en esta parte del código está en store_visit()
. Además de registrar la visita, agrega una tarea a la lista de extracción con la dirección IP del visitante para que este pueda aumentar 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
y un counter
entero para hacer un seguimiento de la cantidad de visitas. Luego, agrega una nueva función (alternativamente, puede ser un classmethod
de Python) llamada fetch_counts()
para buscar y mostrar a los visitantes principales en el 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)
Agregar código de trabajador
Agrega una nueva función log_visitors()
para registrar visitantes a través de una solicitud GET a /log
. Usa un diccionario o hash para hacer un seguimiento de los recuentos de visitantes más recientes, lo que permite asignar tantas tareas como sea posible durante una hora. Para cada tarea, cuenta todas las visitas del mismo visitante. Con los recuentos a 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 la cantidad de 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 nuevos datos de visualización
Para mostrar los visitantes principales, actualiza el controlador principal root()
para invocar a fetch_counts()
. Además, la plantilla se actualizará para mostrar el número de visitantes principales y de las visitas más recientes. Empaqueta el recuento de visitantes junto con las visitas más recientes de la llamada a fetch_visits()
y agrégalos a un solo context
para pasarlo a la plantilla web. A continuación, se muestran los códigos anteriores y posteriores a 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 necesarios para main.py
. A continuación, se incluye una representación ilustrativa de esas actualizaciones con fines ilustrativos para que tengas una idea general de los cambios que realizarás en main.py
:
Actualizar plantilla web con nuevos datos de visualización
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. Suelta los visitantes principales y los recuentos en una tabla en la parte superior de la página y continúa procesando las visitas más recientes como antes. El único cambio adicional consiste en especificar el número que se muestra con la variable limit
en lugar de codificarlo. 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 concluye los cambios necesarios para agregar el uso de tareas de extracción de la lista de tareas en cola de App Engine a la app de ejemplo del módulo 1. Tu directorio ahora representa la app de ejemplo del módulo 18 y debería contener los siguientes archivos:
$ ls README.md appengine_config.py queue.yaml templates app.yaml main.py requirements.txt
6. Resumen/limpieza
En esta sección, se finaliza este codelab implementando la app y verificando que funcione según lo previsto y en cualquier resultado reflejado. Ejecuta el trabajador por separado para procesar el recuento de visitantes. Después de validar la app, realiza los pasos de limpieza y considera los siguientes.
Implementa y verifica la aplicación
Asegúrate de haber configurado tu lista de extracción como lo hicimos cerca de la parte superior de este codelab con gcloud app deploy queue.yaml
. Si el proceso se completó y tu app de ejemplo está lista, implementa la app con gcloud app deploy
. El resultado debería ser idéntico al de la app del Módulo 1, excepto que ahora presenta los "visitantes principales". en la parte superior:
Si bien el frontend web actualizado muestra los visitantes principales y las visitas más recientes, tenga en cuenta que los recuentos de visitantes no incluyen esta visita. La app muestra el recuento de visitantes anteriores mientras descarta una tarea nueva, lo que aumenta el recuento de este visitante en la lista de extracción, una tarea que está a la espera de 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.)
Por ejemplo, si usas curl
para enviar una solicitud GET a /log
, tu resultado se verá de la siguiente manera, si proporcionas tu PROJECT_ID
:
$ curl https://PROJECT_ID.appspot.com/log DONE (with 1 task[s] logging 1 visitor[s])
El recuento actualizado se reflejará en la próxima visita al sitio web. Eso es todo.
Felicitaciones por completar este codelab para agregar correctamente el uso del servicio de lista de extracción de la lista de tareas en cola de App Engine a la app de ejemplo. Ya está listo para migrar a Cloud Pub/Sub, Cloud NDB y Python 3 en el módulo 19.
Limpia
General
Si ya terminaste, te recomendamos que inhabilites la aplicación de App Engine para evitar que se te facture. Sin embargo, si deseas probar o experimentar un poco más, la plataforma de App Engine tiene una cuota gratuita y, siempre y cuando no superes ese nivel de uso, no se te debería cobrar. Eso es para procesamiento, pero es posible que también se apliquen cargos por servicios relevantes de App Engine, así que consulta la página de precios para obtener más información. Si esta migración implica otros servicios de Cloud, estos se facturan por separado. En ambos casos, si corresponde, consulta la sección "Específico de este codelab" a continuación.
Para una divulgación completa, la implementación en una plataforma de procesamiento 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 ocupa parte de esa cuota. Sin embargo, es posible que vivas en una región que no cuenta con ese nivel gratuito, así que ten en cuenta el uso que haces del almacenamiento para minimizar posibles costos. “Carpetas” específicas de Cloud Storage que debes revisar incluyen
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
- Los vínculos de almacenamiento anteriores dependen de tu
PROJECT_ID
y *LOC
*; por ejemplo, "us
" si tu app está alojada en EE.UU.
Por otro lado, si no vas a continuar con esta aplicación o algún otro codelab de migración relacionado y quieres borrar todo por completo, cierra tu proyecto.
Información específica de 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:
- De acuerdo con la página de precios de servicios en paquetes heredados, como la lista de tareas en cola, el servicio de lista de tareas en cola de App Engine no genera facturación adicional.
- El servicio de 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 lista de aplicaciones en cola de la lista de tareas en cola a la app de ejemplo del Módulo 1. Para ello, agregaste compatibilidad con el seguimiento de visitantes y, por lo tanto, implementaste la app de ejemplo 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 finales de 2021, los usuarios ya no tendrán la obligación de migrar a Cloud Pub/Sub cuando actualicen 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 considerar, como Cloud Datastore, Cloud Memorystore, Cloud Storage o Cloud Tasks (listas de aplicaciones en cola). También hay migraciones de productos cruzados a Cloud Run y Cloud Functions. Se puede acceder a todo el contenido de Serverless Migration Station (codelabs, videos, código fuente [si está disponible]) en su repositorio de código abierto.
7. Migración a Python 3
En otoño de 2021, el equipo de App Engine amplió la compatibilidad de muchos de los servicios en paquetes a entornos de ejecución de 2a generación (que tienen un entorno de ejecución de 1a generación). Como resultado, ya no tienes que migrar de servicios agrupados, como la lista de tareas en cola de App Engine, a servicios de Cloud independientes o de terceros, como Cloud Pub/Sub, cuando migras tu aplicación a Python 3. En otras palabras, puedes seguir usando la lista de tareas en cola en las aplicaciones de Python 3 de App Engine, siempre y cuando actualices el código para acceder a servicios en paquetes desde entornos de ejecución de nueva generación.
Puedes obtener más información para migrar el uso de servicios agrupados a Python 3 en el codelab del módulo 17 y el video correspondiente. Si bien ese tema está fuera del alcance del módulo 18, en los vínculos que aparecen a continuación, se encuentran las versiones de Python 3 de la app del módulo 1 transferidas a Python 3 y aún usan App Engine NBS. (En algún momento, también estará disponible una versión de Python 3 de la app del Módulo 18).
8. Recursos adicionales
A continuación, se incluyen recursos adicionales para los desarrolladores que exploran este módulo o uno relacionado, así como productos relacionados. Esto incluye lugares donde enviar comentarios sobre este contenido, vínculos al código y varios documentos que pueden resultarte útiles.
Problemas o comentarios sobre el codelab
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, encontrarás los vínculos a las carpetas del repositorio del Módulo 1 (COMENZAR) y Módulo 18 (FINALIZAR). También se puede acceder a ellas desde el repositorio de todas las migraciones del codelab de App Engine. clonarlo o descargar 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, hay recursos relevantes para este instructivo:
Lista de tareas en cola de App Engine
- Descripción general de la lista de tareas en cola de App Engine
- Descripción general de las listas de extracción de la lista de tareas en cola de App Engine
- App de ejemplo completa de la lista de extracción de la lista de tareas en cola de App Engine
- Crea listas de extracción de la lista de tareas en cola
- Video del lanzamiento de la lista de extracción de Google I/O 2011 ( app de ejemplo de Votarlator)
- Referencia de
queue.yaml
queue.yaml
vs. Cloud Tasks- Guía de migración de listas de extracción a Pub/Sub
- Ejemplo de documentación de las listas de extracción de la lista de tareas en cola de App Engine para Cloud Pub/Sub
Plataforma de App Engine
Documentación de App Engine
Entorno de ejecución de App Engine (entorno estándar) para Python 2
Entorno de ejecución de App Engine (entorno estándar) para Python 3
Diferencias entre Python 2 y 3 entornos de ejecución de App Engine (entorno estándar)
Guía de migración de Python 2 a 3 de App Engine (entorno estándar)
Información de precios y cuotas de App Engine
Lanzamiento de la plataforma de 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 Cloud
- Python en Google Cloud Platform
- Bibliotecas cliente de Python de Google Cloud
- Google Cloud “Siempre gratuito” nivel
- SDK de Google Cloud (herramienta de línea de comandos de
gcloud
) - Toda la documentación de Google Cloud
Videos
- Estación de migración sin servidores
- 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.