Esta serie de Codelabs (instructivos prácticos y de autoaprendizaje) tienen como objetivo ayudar a los desarrolladores de Google App Engine (estándar) a modernizar sus apps con una serie de migraciones. El paso más importante es dejar de lado los servicios agrupados del entorno de ejecución porque los entornos de ejecución de última generación son más flexibles y ofrecen a los usuarios una mayor variedad de opciones de servicios. El cambio al entorno de ejecución de generación más reciente te permite la integración en productos de Google Cloud con más facilidad, usar una mayor variedad de servicios compatibles y admitir versiones actuales de lenguaje.
Este codelab ayuda a los usuarios a migrar de las tareas de envío de App Engine y de la API o biblioteca de taskqueue
a Cloud Tasks. Si tu aplicación no usa las listas de tareas en cola, puedes usar este codelab como ejercicio para aprender a migrar tareas de envío de App Engine a Cloud Tasks.
Obtendrás información para hacer las siguientes acciones
- Migrar de App Engine
taskqueue
a Cloud Tasks - Crea tareas de envío con Cloud Tasks
- Migra de
ndb
de App Engine a Cloud NDB (igual que el módulo 2)
Qué necesitará
- Un proyecto de Google Cloud Platform con lo siguiente:
- 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
- Se recomienda completar el codelab Módulo 7 antes de comenzar este (módulo 8).
- Una app de App Engine en el módulo 7 funcionamiento
Encuesta
¿Cómo usarás este codelab?
Ya que agregamos tareas de envío de App Engine a la aplicación de muestra en el codelab anterior (Módulo 7), ahora podemos migrarla a Cloud Tasks. En la migración de este instructivo, se incluyen los siguientes pasos principales:
- Configurar/trabajo previo
- Actualizar archivos de configuración
- Actualizar la aplicación principal
Antes de comenzar con la parte principal del instructivo, configuremos nuestro proyecto, obtengamos el código e implementemos la app de modelo de referencia para que comencemos a trabajar con el código.
1. Configura el proyecto
Te recomendamos que vuelvas a usar el mismo proyecto que usaste para completar el Codelab del Módulo 7. 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 que App Engine (app) esté habilitado.
2. Obtén app de ejemplo del modelo de referencia
Uno de los requisitos de este codelab es tener una app de ejemplo del Módulo 7 en funcionamiento. Si no tienes uno, te recomendamos que completes el instructivo del Módulo 7 (vínculo arriba) antes de continuar. De lo contrario, si ya estás familiarizado con su contenido, puedes comenzar leyendo el código del Módulo 7 a continuación.
Sin importar si usas el tuyo o el nuestro, el código del Módulo 7 es el que tendremos en cuenta. Este codelab del módulo 2 te guiará en cada paso y, cuando se complete, debería parecerse al código en el punto FINALIZAR (incluido un puerto de opcional de Python 2 a 3):
- INICIAR: Repositorio del módulo 7
- FINALIZAR: Repositorio del módulo 8
- Repositorio completo (clonar o descargar el archivo ZIP)
El directorio de archivos del módulo 7 (el tuyo o el nuestro) debe verse así:
$ ls
README.md appengine_config.py requirements.txt
app.yaml main.py templates
Si completaste el instructivo del módulo 7, también tendrás una carpeta lib
con Flask y sus dependencias.
3. (Vuelve a ) implementar la app del Módulo 7
Los pasos del trabajo previo restantes para ejecutar ahora sin estos:
- Vuelve a familiarizarte con la herramienta de línea de comandos de
gcloud
(si es necesario). - (Vuelve a )implementa el código del módulo 7 en App Engine (si es necesario).
Después de ejecutar esos pasos de forma correcta y confirmemos que está funcionando, avanzaremos en este instructivo y comenzaremos con los archivos de configuración.
requirements.txt
El requirements.txt
del módulo 7 solo enumera Flask como un paquete obligatorio. Cloud NDB y Cloud Tasks tienen sus propias bibliotecas cliente, por lo que, en este paso, agrega esos paquetes a requirements.txt
para que se vea de la siguiente manera:
Flask==1.1.2
google-cloud-ndb==1.7.1
google-cloud-tasks==1.5.0
Recomendamos usar las versiones más recientes de cada biblioteca. Los números de las versiones anteriores son los más recientes de Python 2 en el momento en que se redactó este documento. (Es probable que los paquetes equivalentes de Python 3 estén en versiones posteriores). El código en la carpeta del repositorio FINALIZAR se actualiza con más frecuencia y puede tener versiones más recientes, a pesar de que esto no sea así. Las bibliotecas de Python 2 que generalmente se inmovilizan.
app.yaml
Haz referencia a las bibliotecas integradas grpcio
y setuptools
en app.yaml
en una sección libraries
:
libraries:
- name: grpcio
version: 1.0.0
- name: setuptools
version: 36.6.0
appengine_config.py
Actualiza appengine_config.py
para usar pkg_resources
a fin de vincular las bibliotecas integradas a las bibliotecas de terceros copiadas, como Flask y las bibliotecas cliente de Google Cloud:
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)
Solo hay un archivo de aplicación, main.py
, por lo que todos los cambios de esta sección afectan solo a ese archivo.
Actualizar las importaciones y la inicialización
En este momento, nuestra app usa las bibliotecas integradas google.appengine.api.taskqueue
y google.appengine.ext.ndb
:
- ANTES:
from datetime import datetime
import logging
import time
from flask import Flask, render_template, request
from google.appengine.api import taskqueue
from google.appengine.ext import ndb
Reemplaza ambos con google.cloud.ndb
y google.cloud.tasks
. Además, Cloud Tasks requiere que codifiques en JSON la carga útil de la tarea, por lo que también debes importar json
. Cuando hayas terminado, la sección import
de main.py
debería verse de la siguiente manera:
- DESPUÉS:
from datetime import datetime
import json
import logging
import time
from flask import Flask, render_template, request
from google.cloud import ndb, tasks
Migra a Cloud Tasks (y Cloud NDB)
- ANTES:
def store_visit(remote_addr, user_agent):
'create new Visit entity in Datastore'
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
No hay cambios en store_visit()
distintos de lo que hiciste en el módulo 2: agrega un administrador de contexto a todo el acceso de Datastore. Esto se aplica en la creación de una nueva entidad Visit
en una declaración with
.
- DESPUÉS:
def store_visit(remote_addr, user_agent):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
Por el momento, Cloud Tasks requiere que App Engine esté habilitado para tu proyecto de Google Cloud a fin de poder usarlo (incluso si no tienes el código de App Engine). De lo contrario, las listas de tareas en cola no funcionarán. (consulta esta sección en los documentos para obtener más información). Cloud Tasks admite tareas que se ejecutan en App Engine (“objetivos de App Engine”), pero también se puede ejecutar en cualquier extremo HTTP (destinos HTTP) con una dirección IP pública, como Cloud Functions, Cloud Run, GKE, Compute Engine o incluso un servidor web local. Nuestra app simple usa un destino de App Engine para las tareas.
Se requiere cierta configuración para usar Cloud NDB y Cloud Tasks. En la parte superior de main.py
, en la inicialización de Flask, inicializa Cloud NDB y Cloud Tasks. Define también algunas constantes que indiquen dónde se ejecutarán tus tareas de aplicaciones en cola.
app = Flask(__name__)
ds_client = ndb.Client()
ts_client = tasks.CloudTasksClient()
PROJECT_ID = 'PROJECT_ID' # replace w/your own
REGION = 'REGION' # replace w/your own
QUEUE_NAME = 'default' # replace w/your own if desired
QUEUE_PATH = ts_client.queue_path(PROJECT_ID, REGION, QUEUE_NAME)
Una vez que crees la lista de tareas en cola, completa el PROJECT_ID
de tu proyecto, la REGION
en la que se ejecutarán tus tareas (debe ser la misma que en tu región de App Engine) y el nombre de tu lista de aplicaciones en cola. App Engine muestra una cola “default
”, por lo que usaremos ese nombre (pero no es necesario).
La cola default
es especial y se crea automáticamente en ciertas circunstancias; una de ellas es cuando se usan las API de App Engine, por lo que reutilizas el mismo proyecto que en el módulo 7, default
ya existirán. Sin embargo, si creaste un proyecto nuevo específicamente para el módulo 8, deberás crear default
de forma manual. Puedes encontrar más información sobre la cola de default
en la documentación de queue.yaml
.
El objetivo de ts_client.queue_path()
es crear el “nombre de la ruta de acceso completamente calificado” de la lista de tareas en cola (QUEUE_PATH
) que se necesita para crear una tarea. También es necesaria una estructura JSON que especifique los parámetros de la tarea:
task = {
'app_engine_http_request': {
'relative_uri': '/trim',
'body': json.dumps({'oldest': oldest}).encode(),
'headers': {
'Content-Type': 'application/json',
},
}
}
¿Qué estás viendo arriba?
- Proporciona información sobre el objetivo de la tarea:
- Para los objetivos de App Engine, especifica
app_engine_http_request
como el tipo de solicitud yrelative_uri
es el controlador de tareas de App Engine. - Para los destinos HTTP, en su lugar usa
http_request
yurl
.
- Para los objetivos de App Engine, especifica
body
: los parámetros codificados en strings JSON y Unicode que se envían a la tarea (enviar)- Especifica un encabezado
Content-Type
codificado en JSON de manera explícita
Consulte la documentación para obtener más información sobre sus opciones aquí.
Con la configuración al margen, actualicemos fetch_visits()
. A continuación, se muestra como se ve en el instructivo anterior:
- ANTES:
def fetch_visits(limit):
'get most recent visits and add task to delete older visits'
data = Visit.query().order(-Visit.timestamp).fetch(limit)
oldest = time.mktime(data[-1].timestamp.timetuple())
oldest_str = time.ctime(oldest)
logging.info('Delete entities older than %s' % oldest_str)
taskqueue.add(url='/trim', params={'oldest': oldest})
return (v.to_dict() for v in data), oldest_str
Se requieren las siguientes actualizaciones:
- Cambia de App Engine
ndb
a Cloud NDB - Código nuevo para extraer la marca de tiempo de la visita más antigua mostrada
- Usa Cloud Tasks para crear una nueva tarea en lugar
taskqueue
de App Engine
Tu nuevo fetch_visits()
debería verse de la siguiente manera:
- DESPUÉS:
def fetch_visits(limit):
'get most recent visits and add task to delete older visits'
with ds_client.context():
data = Visit.query().order(-Visit.timestamp).fetch(limit)
oldest = time.mktime(data[-1].timestamp.timetuple())
oldest_str = time.ctime(oldest)
logging.info('Delete entities older than %s' % oldest_str)
task = {
'app_engine_http_request': {
'relative_uri': '/trim',
'body': json.dumps({'oldest': oldest}).encode(),
'headers': {
'Content-Type': 'application/json',
},
}
}
ts_client.create_task(parent=QUEUE_PATH, task=task)
return (v.to_dict() for v in data), oldest_str
Resumen de la actualización del código:
- Cambiar a Cloud NDB significa mover el código de Datastore dentro de una declaración
with
- Cambiar a Cloud Tasks significa usar
ts_client.create_task()
en lugar detaskqueue.add()
- Pasa la ruta de acceso completa de la cola y la carga útil
task
(que se describió antes)
Actualiza el controlador de tareas (envío)
Hay muy pocos cambios que se deben realizar en la función del controlador de tareas (envío).
- ANTES:
@app.route('/trim', methods=['POST'])
def trim():
'(push) task queue handler to delete oldest visits'
oldest = request.form.get('oldest', type=float)
keys = Visit.query(
Visit.timestamp < datetime.fromtimestamp(oldest)
).fetch(keys_only=True)
nkeys = len(keys)
if nkeys:
logging.info('Deleting %d entities: %s' % (
nkeys, ', '.join(str(k.id()) for k in keys)))
ndb.delete_multi(keys)
else:
logging.info('No entities older than: %s' % time.ctime(oldest))
return '' # need to return SOME string w/200
Lo único que se debe hacer es colocar todo el acceso de Datastore dentro de la instrucción with
del administrador de contexto, tanto la solicitud de consulta como la de eliminación. En este sentido, actualiza el controlador trim()
de la siguiente manera:
- DESPUÉS:
@app.route('/trim', methods=['POST'])
def trim():
'(push) task queue handler to delete oldest visits'
oldest = float(request.get_json().get('oldest'))
with ds_client.context():
keys = Visit.query(
Visit.timestamp < datetime.fromtimestamp(oldest)
).fetch(keys_only=True)
nkeys = len(keys)
if nkeys:
logging.info('Deleting %d entities: %s' % (
nkeys, ', '.join(str(k.id()) for k in keys)))
ndb.delete_multi(keys)
else:
logging.info('No entities older than: %s' % time.ctime(oldest))
return '' # need to return SOME string w/200
No hay cambios en templates/index.html
en este o en el siguiente codelab.
Implemente la aplicación
Vuelve a verificar todos los cambios que compila tu código y vuelve a implementarlo. Confirma que la app (todavía) funciona. Se espera un resultado idéntico al del módulo 7. Como acabamos de restablecer todo tipo de energía, todo debería funcionar como se espera.
Si llegaste a este instructivo sin realizar el codelab del módulo 7, la app en sí no cambiará. registra todas las visitas a la página web principal (/
) y tendrá este aspecto una vez que visitas el sitio con el tiempo suficiente y te indica que borró todas las visitas anteriores a la décima.
Con esto concluye este codelab. El código ahora debería coincidir con el contenido del repositorio del módulo 8. Felicitaciones por completar la migración más importante de las tareas de envío. El módulo 9 (vínculo al codelab siguiente) es opcional, y ayuda a los usuarios a pasar a Python 3 y a Cloud Datastore.
Opcional: Limpieza
¿Qué te parece limpiar a fin de evitar que se te facture hasta que estés listo para pasar a la siguiente codelab de migración? Como desarrolladores existentes, es probable que ya estés al día en la información sobre precios de App Engine.
Opcional: Inhabilita la app
Si aún no estás listo para continuar con el siguiente instructivo, inhabilita tu app a fin de evitar que se apliquen cargos. Cuando estés listo para pasar al siguiente codelab, puedes volver a habilitarla. Aunque tu app esté inhabilitada, no recibirá tráfico que genere cargos. Sin embargo, si se excede la cuota gratuita, se te cobrará por el uso de Datastore. así que borra lo suficiente para que quede dentro de ese límite.
Por otro lado, si no vas a continuar con las migraciones y quieres borrar todo por completo, puedes cerrar tu proyecto.
Próximos pasos
Más allá de este instructivo, el siguiente paso es el módulo 9 y su codelab, y cómo trasladarse a Python 3. Es opcional, ya que no todos están listos para ese paso. También hay un puerto opcional de Cloud NDB a Cloud Datastore, que es definitivamente opcional, y solo para aquellos que desean salir de NDB y el código consolidado que usa Cloud Datastore. Esa migración es idéntica al Codelab de migración del módulo 3.
- Módulo 9 Migra de Python 2 a 3 y Cloud NDB a Cloud Datastore
- Portar módulos de migración opcionales a Python 3
- También incluye una migración opcional de Cloud NDB a Cloud Datastore (igual que el módulo 3)
- Una migración menor de Cloud Tasks v1 a v2 (ya que su biblioteca cliente está inactiva para Python 2)
- Módulo 4: Migra a Cloud Run con Docker
- Organiza tu aplicación en contenedores para que se ejecute en Cloud Run con Docker
- Esta migración te permite permanecer en Python 2.
- Módulo 5: Migra a Cloud Run con Cloud Buildpacks
- Crea contenedores para tu app a fin de que se ejecute en Cloud Run con paquetes de Cloud Build
- No necesitas conocer los detalles de Docker, contenedores, ni
Dockerfile
. - Requiere que tu app ya se haya migrado a Python 3 (Buildpacks no es compatible con Python 2).
- Módulo 6: Migra a Cloud Firestore
- Migra a Cloud Firestore para acceder a las funciones de Firebase
- Si bien Cloud Firestore es compatible con Python 2, este codelab solo está disponible en Python 3.
Problemas o comentarios de los Codelabs del módulo de migración de App Engine
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
Puede encontrar vínculos a las carpetas del repositorio para el módulo 7 (INICIAR) y el módulo 8 (FINALIZAR) en la tabla a continuación. También se puede acceder a ellos desde el repositorio de todas las migraciones de codelab de App Engine, que te permite clonar o descargar un archivo ZIP.
Codelab | Python 2 | Python 3 |
(n/a) | ||
Módulo 8 | (n/a) |
Recursos de App Engine
A continuación, se muestran recursos adicionales con respecto a esta migración específica:
- Referencias
ndb
de App Engine y Cloud NDB - Referencias de App Engine
taskqueue
y Cloud Tasks - Migra a Python 3 y GAE de entorno de ejecución de última generación
- General