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.
El propósito de este codelab es mostrarles a los desarrolladores de App Engine de Python 2 cómo migrar desde las tareas de extracción de la lista de tareas en cola de App Engine a Cloud Pub/Sub. También hay una migración implícita de App Engine NDB a Cloud NDB para el acceso a Datastore (que se aborda principalmente en el Módulo 2), así como una actualización a Python 3.
En el módulo 18, aprenderás a agregar el uso de tareas de extracción a tu app. En este módulo, tomarás la app finalizada del Módulo 18 y migrarás ese uso a Cloud Pub/Sub. 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,
- Reemplaza el uso de la lista de tareas en cola de App Engine (tareas de extracción) por Cloud Pub/Sub.
- Reemplaza el uso de App Engine NDB por Cloud NDB (consulta también el Módulo 2).
- Cómo realizar la portabilidad de la app a Python 3
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 ejemplo del Módulo 18 de App Engine en funcionamiento
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
La lista de tareas en cola de App Engine admite tareas de envío y extracción. Para mejorar la portabilidad de la aplicación, Google Cloud recomienda migrar de servicios en paquetes heredados, como la lista de tareas en cola, a otros servicios independientes o equivalentes de terceros de Cloud.
- Los usuarios de la tarea push de la lista de tareas en cola deben migrar a Cloud Tasks.
- Los usuarios de la tarea de extracción de la lista de tareas en cola deben migrar a Cloud Pub/Sub.
Los módulos 7 a 9 de migración abordan la migración de tareas push, mientras que los módulos 18 a 19 se enfocan en la migración de tareas de extracción. Si bien Cloud Tasks coincide más con las tareas push de la lista de tareas en cola, Pub/Sub no es tan parecido a las tareas de extracción de la lista de tareas en cola.
Pub/Sub tiene más funciones que la funcionalidad de extracción que proporciona la lista de tareas en cola. Por ejemplo, Pub/Sub también tiene la funcionalidad push, sin embargo, Cloud Tasks se parece más a las tareas push de la lista de tareas en cola, por lo que Pub/Sub no está cubierto por ninguno de los módulos de migración. En este codelab del módulo 19, se muestra cómo cambiar el mecanismo de cola de las listas de extracción de la lista de tareas en cola a Pub/Sub, así como migrar de App Engine NDB a Cloud NDB para el acceso a Datastore, lo que repite la migración del Módulo 2.
Mientras que el código del módulo 18 es como app de muestra de Python 2, la fuente en sí es compatible con Python 2 y 3, y se mantiene así incluso después de migrar a Cloud Pub/Sub (y Cloud NDB) en el 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
- Habilitar nuevas APIs o servicios de Google Cloud
Estos pasos garantizan que comiences con el código de trabajo y que esté listo para migrar a los servicios de Cloud.
1. Configura el proyecto
Si completaste el codelab del módulo 18, 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 necesitarás tenerlo a mano durante este codelab, utilízalo cada vez que encuentres la variable PROJECT_ID
.
2. Obtén app de ejemplo del modelo de referencia
Uno de los requisitos previos es contar con una app de App Engine del Módulo 18 que funcione, así que completa el codelab (se recomienda incluir el vínculo anterior) o copia el código del módulo 18 del repositorio. Ya sea que use el suyo o el nuestro, aquí es por donde comenzaremos ("COMENZAR"). En este codelab, se explica la migración y se concluye con un código similar al que hay en la carpeta del repositorio del Módulo 19 (“FINISH”).
- INICIO: Carpeta del módulo 18 (Python 2)
- FIN: Carpeta del módulo 19 (Python 2 y 3)
- Repositorio completo (para clonar o descargar un archivo ZIP)
Independientemente de la app del Módulo 18 que uses, la carpeta debería verse de la siguiente manera, posiblemente con una carpeta lib
:
$ ls README.md appengine_config.py queue.yaml templates app.yaml main.py requirements.txt
3. (Re)Implementa y valida la app de referencia
Ejecuta los siguientes pasos para implementar la app del módulo 18:
- Borra la carpeta
lib
si hay una y ejecutapip install -t lib -r requirements.txt
para volver a propagarlib
. Es posible que debas usarpip2
si tienes Python 2 y 3 instalados en tu máquina de desarrollo. - Asegúrate de haber instalado e inicializado la herramienta de línea de comandos de
gcloud
y de haber revisado su uso. - (Opcional) Configura tu proyecto de Cloud con
gcloud config set project
PROJECT_ID
si no quieres ingresar elPROJECT_ID
con cada comandogcloud
que emitas. - Implementa la app de ejemplo con
gcloud app deploy
- Confirma que la app se ejecute como se espera sin problemas. Si completaste el codelab del módulo 18, la app mostrará los visitantes principales junto con las visitas más recientes (que se ilustran a continuación). De lo contrario, es posible que no se muestren recuentos de visitantes.
Antes de migrar la app de muestra del módulo 18, primero debes habilitar los servicios de Cloud que usará la app modificada.
4. Habilitar nuevas APIs o servicios de Google Cloud
La app antigua usaba servicios en paquetes de App Engine que no requieren una configuración adicional, pero los servicios de Cloud independientes sí lo hacen, y la app actualizada empleará Cloud Pub/Sub y Cloud Datastore (a través de la biblioteca cliente de Cloud NDB). App Engine y ambas APIs de Cloud tienen la opción “Siempre gratuito” nivel y, siempre que te mantengas por debajo de esos límites, no se generarán cargos si completas este instructivo. Las APIs de Cloud se pueden habilitar desde la consola de Cloud o desde la línea de comandos, según tus preferencias.
Desde la consola de Cloud
Ve a la página Biblioteca del Administrador de API (del proyecto correcto) en la consola de Cloud y busca las APIs de Cloud Datastore y Cloud Pub/Sub con la barra de búsqueda que aparece en el medio de la página:
Haz clic en el botón Habilitar para cada API por separado; es posible que se te soliciten datos de facturación. Por ejemplo, esta es la página de la biblioteca de la API de Cloud Pub/Sub:
Desde la línea de comandos
Si bien es visualmente informativo habilitar APIs desde la consola, algunos prefieren la línea de comandos. Ejecuta el comando gcloud services enable pubsub.googleapis.com datastore.googleapis.com
para habilitar ambas APIs al mismo tiempo:
$ gcloud services enable pubsub.googleapis.com datastore.googleapis.com Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.
Es posible que se le soliciten datos de facturación. Si quieres habilitar otras APIs de Cloud y conocer sus URI, puedes encontrarlas en la parte inferior de la página de la biblioteca de cada API. Por ejemplo, observa pubsub.googleapis.com
como el "Nombre del servicio" en la parte inferior de la página de Pub/Sub, arriba.
Una vez que completes los pasos, tu proyecto podrá acceder a las APIs. Ahora es el momento de actualizar la aplicación para usar esas APIs.
4. Crea recursos de Pub/Sub
Resumen del orden de secuencias del flujo de trabajo de la lista de tareas en cola del Módulo 18:
- En el módulo 18, se usó el archivo
queue.yaml
para crear una lista de extracción llamadapullq
. - La app agrega tareas a la lista de extracción para hacer un seguimiento de los visitantes.
- Un trabajador procesa las tareas y las asigna durante un tiempo limitado (una hora).
- Se ejecutan tareas para contar los recuentos recientes de visitantes.
- Las tareas se borran de la cola cuando se completan.
Vas a replicar un flujo de trabajo similar con Pub/Sub. En la siguiente sección, se presenta la terminología básica de Pub/Sub, con tres formas diferentes de crear los recursos de Pub/Sub necesarios.
Comparación entre la terminología de lista de tareas en cola (extracción) de App Engine y Cloud Pub/Sub
Para cambiar a Pub/Sub, debes ajustar levemente tu vocabulario. A continuación, se indican las categorías principales junto con los términos relevantes de ambos productos. Además, revisa la guía de migración, que incluye comparaciones similares.
- Estructura de datos en cola: con la lista de tareas en cola, los datos pasan a listas de extracción. con Pub/Sub, los datos se dividen en temas.
- Unidades de datos en cola: las tareas de extracción con la lista de tareas en cola se denominan mensajes con Pub/Sub.
- Procesadores de datos: Con la lista de tareas en cola, los trabajadores acceden a las tareas de extracción. con Pub/Sub, necesitas suscripciones/suscriptores para recibir mensajes
- Extracción de datos: Dejar una tarea de extracción es lo mismo que extraer un mensaje de un tema (a través de una suscripción).
- Limpieza y finalización: Borrar una tarea de la lista de tareas en cola de una lista de extracción al terminar es similar a confirmar un mensaje de Pub/Sub.
Aunque el producto en cola cambia, el flujo de trabajo sigue siendo relativamente similar:
- En lugar de una lista de extracción, la app usa un tema llamado
pullq
. - En lugar de agregar tareas a una lista de extracción, la app envía mensajes a un tema (
pullq
). - En lugar de que un trabajador lea las tareas de la lista de extracción, un suscriptor llamado
worker
extrae los mensajes del temapullq
. - La app procesa las cargas útiles de mensajes, lo que aumenta el recuento de visitantes en Datastore.
- En lugar de borrar tareas de la lista de extracción, la app confirma los mensajes procesados.
Con la lista de tareas en cola, la configuración implica crear una lista de extracción. Con Pub/Sub, la configuración requiere la creación de un tema y una suscripción. En el módulo 18, procesamos queue.yaml
fuera de la ejecución de la app. lo mismo debe hacerse con Pub/Sub.
Existen tres opciones para crear temas y suscripciones:
- Desde la consola de Cloud
- Desde la línea de comandos
- Desde el código (secuencia de comandos corta de Python)
Elige una de las opciones que aparecen a continuación y sigue las instrucciones correspondientes para crear tus recursos de Pub/Sub.
Desde la consola de Cloud
Para crear un tema desde la consola de Cloud, sigue estos pasos:
- Ve a la página Temas de Pub/Sub de Cloud Console.
- Haz clic en Crear tema en la parte superior. se abre un nuevo cuadro de diálogo (consulta la imagen a continuación).
- En el campo ID del tema, ingresa
pullq
. - Anula la selección de todas las opciones marcadas y elige Clave de encriptación administrada por Google.
- Haz clic en el botón Crear tema.
Así se ve el diálogo de creación de temas:
Ahora que tienes un tema, debes crear una suscripción para él:
- Ve a la página Suscripciones de Pub/Sub de la consola de Cloud.
- Haz clic en Crear suscripción en la parte superior (consulta la siguiente imagen).
- Ingresa
worker
en el campo ID de la suscripción. - Elige
pullq
en el menú desplegable Seleccionar un tema de Cloud Pub/Sub y presta atención a su "nombre de ruta completamente calificado". por ejemplo,projects/PROJECT_ID/topics/pullq
- En Tipo de entrega, selecciona Extracción.
- Deja todas las demás opciones como están y haz clic en el botón Crear.
Así se ve la pantalla de creación de la suscripción:
También puede crear una suscripción desde la página Temas, este "acceso directo" puede resultarte útil para ayudar a asociar temas con suscripciones. Para obtener más información sobre cómo crear suscripciones, consulta la documentación.
Desde la línea de comandos
Los usuarios de Pub/Sub pueden crear temas y suscripciones con los comandos gcloud pubsub topics create
TOPIC_ID
y gcloud pubsub subscriptions create
SUBSCRIPTION_ID
--topic=
TOPIC_ID
, respectivamente. Si se ejecutan con una TOPIC_ID
de pullq
y una SUBSCRIPTION_ID
de worker
, se obtiene el siguiente resultado para el proyecto PROJECT_ID
:
$ gcloud pubsub topics create pullq Created topic [projects/PROJECT_ID/topics/pullq]. $ gcloud pubsub subscriptions create worker --topic=pullq Created subscription [projects/PROJECT_ID/subscriptions/worker].
Consulta también esta página en la documentación de la guía de inicio rápido. Usar la línea de comandos podría simplificar los flujos de trabajo en los que los temas y las suscripciones se crean de forma regular, y esos comandos se pueden usar en las secuencias de comandos de shell para este propósito.
Desde el código (secuencia de comandos corta de Python)
Otra forma de automatizar la creación de temas y suscripciones es usar la API de Pub/Sub en el código fuente. El siguiente es el código de la secuencia de comandos maker.py
en la carpeta del repositorio del módulo 19.
from __future__ import print_function
import google.auth
from google.api_core import exceptions
from google.cloud import pubsub
_, PROJECT_ID = google.auth.default()
TOPIC = 'pullq'
SBSCR = 'worker'
ppc_client = pubsub.PublisherClient()
psc_client = pubsub.SubscriberClient()
TOP_PATH = ppc_client.topic_path(PROJECT_ID, TOPIC)
SUB_PATH = psc_client.subscription_path(PROJECT_ID, SBSCR)
def make_top():
try:
top = ppc_client.create_topic(name=TOP_PATH)
print('Created topic %r (%s)' % (TOPIC, top.name))
except exceptions.AlreadyExists:
print('Topic %r already exists at %r' % (TOPIC, TOP_PATH))
def make_sub():
try:
sub = psc_client.create_subscription(name=SUB_PATH, topic=TOP_PATH)
print('Subscription created %r (%s)' % (SBSCR, sub.name))
except exceptions.AlreadyExists:
print('Subscription %r already exists at %r' % (SBSCR, SUB_PATH))
try:
psc_client.close()
except AttributeError: # special Py2 handler for grpcio<1.12.0
pass
make_top()
make_sub()
La ejecución de esta secuencia de comandos da como resultado el resultado esperado (siempre y cuando no haya errores):
$ python3 maker.py Created topic 'pullq' (projects/PROJECT_ID/topics/pullq) Subscription created 'worker' (projects/PROJECT_ID/subscriptions/worker)
Llamar a la API para crear recursos existentes genera una excepción google.api_core.exceptions.AlreadyExists
que arroja la biblioteca cliente y que la secuencia de comandos controla de forma correcta:
$ python3 maker.py Topic 'pullq' already exists at 'projects/PROJECT_ID/topics/pullq' Subscription 'worker' already exists at 'projects/PROJECT_ID/subscriptions/worker'
Si es la primera vez que usas Pub/Sub, consulta el informe sobre la arquitectura de Pub/Sub para obtener más información.
5. Actualizar configuración
Las actualizaciones de la configuración incluyen el cambio de varios archivos de configuración y la creación del equivalente de listas de extracción de App Engine, pero dentro del ecosistema de Cloud Pub/Sub.
Borra queue.yaml
Estamos saliendo de la lista de tareas en cola por completo, por lo que debes borrar queue.yaml
porque Pub/Sub no usa este archivo. En lugar de crear una lista de extracción, deberás crear un tema de Pub/Sub (y una suscripción).
requirements.txt
Agrega google-cloud-ndb
y google-cloud-pubsub
a requirements.txt
para unir flask
del módulo 18. La actualización requirements.txt
del módulo 19 debería verse de la siguiente manera:
flask
google-cloud-ndb
google-cloud-pubsub
Este archivo requirements.txt
no presenta ningún número de versión, lo que significa que se seleccionaron las versiones más recientes. Si surge alguna incompatibilidad, sigue la práctica estándar de usar números de versión para bloquear versiones de trabajo de una app.
app.yaml
Los cambios a app.yaml
difieren en función de si te quedas con Python 2 o actualizas a Python 3.
Python 2
La actualización anterior de requirements.txt
agrega el uso de las bibliotecas cliente de Google Cloud. Estas requieren asistencia adicional de App Engine, en particular, un par de bibliotecas integradas, setuptools
y grpcio
. El uso de bibliotecas integradas requiere una sección libraries
en app.yaml
y números de versión de biblioteca o “más reciente” para conocer las últimas novedades sobre los servidores de App Engine. El módulo 18 app.yaml
aún no tiene una de esas secciones:
ANTES:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
Agrega una sección libraries
a app.yaml
junto con entradas para setuptools
y grpcio
, y selecciona las versiones más recientes. Además, agrega una entrada de marcador de posición runtime
para Python 3, comentada junto con una versión 3.x actual, por ejemplo, 3.10, en el momento de la redacción de este documento. Con estos cambios, app.yaml
ahora tendrá el siguiente aspecto:
DESPUÉS:
#runtime: python310
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: setuptools
version: latest
- name: grpcio
version: latest
Python 3
Para los usuarios de Python 3 y app.yaml
, se trata de quitar elementos. En esta sección, borrarás la sección handlers
y las directivas threadsafe
y api_version
, y no crearás una sección libraries
.
Los entornos de ejecución de segunda generación no proporcionan bibliotecas de terceros integradas, por lo que no se necesita una sección libraries
en app.yaml
. Además, ya no se requiere la copia de paquetes de terceros (también conocida como proveedor o autoagrupación) no integrados. Solo debes enumerar las bibliotecas de terceros que usa tu app en requirements.txt
.
La sección handlers
de app.yaml
se usa para especificar controladores de aplicaciones (secuencia de comandos) y de archivos estáticos. Dado que el entorno de ejecución de Python 3 requiere frameworks web para realizar su propio enrutamiento, todos los controladores de secuencia de comandos deben cambiarse a auto
. Si tu app (como la del Módulo 18) no entrega archivos estáticos, todas las rutas serían auto
, por lo que son irrelevantes. Como resultado, la sección handlers
tampoco es necesaria, así que bórrala.
Por último, en Python 3 no se usan las directivas threadsafe
ni api_version
, así que bórralas también. En conclusión, debes borrar todas las secciones de app.yaml
para que solo quede la directiva runtime
y se especifique una versión moderna de Python 3, por ejemplo, 3.10. Así se ve app.yaml
antes y después de estas actualizaciones:
ANTES:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
DESPUÉS:
runtime: python310
Para aquellos que no están listos para borrar todo de su app.yaml
para Python 3, proporcionamos un archivo alternativo app3.yaml
en la carpeta del repositorio del módulo 19. Si deseas usarla en su lugar para las implementaciones, asegúrate de agregar este nombre de archivo al final de tu comando: gcloud app deploy app3.yaml
(de lo contrario, se implementará la app de forma predeterminada con el archivo app.yaml
de Python 2 que no modificaste).
appengine_config.py
Si actualizas a Python 3, no es necesario usar appengine_config.py
, así que bórralo. Esto no es necesario porque la compatibilidad con bibliotecas de terceros solo requiere que se especifiquen en requirements.txt
. usuarios de Python 2, continúa leyendo.
El appengine_config.py
del módulo 18 tiene el código apropiado para admitir bibliotecas de terceros, por ejemplo, Flask y las bibliotecas cliente de Cloud que se acaban de agregar a requirements.txt
:
ANTES:
from google.appengine.ext import vendor
# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
Sin embargo, este código por sí solo no es suficiente para admitir las bibliotecas integradas que se acaban de agregar (setuptools
, grpcio
). Necesitan algunas líneas más, así que actualiza appengine_config.py
para que se vea de la siguiente manera:
DESPUÉS:
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)
Puedes encontrar más detalles sobre los cambios necesarios para admitir las bibliotecas cliente de Cloud en la documentación sobre migración de servicios en paquetes.
Otras actualizaciones de configuración
Si tienes una carpeta lib
, bórrala. Si eres usuario de Python 2, recarga la carpeta lib
con el siguiente comando:
pip install -t lib -r requirements.txt # or pip2
Si tienes Python 2 y 3 instalados en tu sistema de desarrollo, es posible que debas usar pip2
en lugar de pip
.
6. Modifica el código de la aplicación
En esta sección, se presentan actualizaciones del archivo principal de la aplicación, main.py
, y se reemplaza el uso de las listas de extracción de la lista de tareas en cola de App Engine con Cloud Pub/Sub. No hay cambios en la plantilla web, templates/index.html
. Ambas apps deben funcionar de forma idéntica y mostrar los mismos datos.
Actualizar las importaciones y la inicialización
Hay varias actualizaciones para las importaciones y la inicialización:
- Para las importaciones, reemplaza App Engine NDB y la lista de tareas en cola con Cloud NDB y Pub/Sub.
- Cambia el nombre de
pullq
deQUEUE
aTOPIC
. - Con las tareas de extracción, el trabajador las asignó durante una hora, pero con Pub/Sub, los tiempos de espera se miden por mensaje, por lo que debes borrar la constante
HOUR
. - Las APIs de Cloud requieren el uso de un cliente de API, por lo que debes iniciarlas para Cloud NDB y Cloud Pub/Sub. Esta última función proporciona clientes para los temas y las suscripciones.
- Pub/Sub requiere el ID del proyecto de Cloud, así que impórtalo y obtenlo de
google.auth.default()
. - Pub/Sub requiere “nombres de rutas de acceso completamente calificados” para temas y suscripciones, así que créalos usando las funciones prácticas de
*_path()
.
A continuación, se muestran las importaciones y la inicialización del módulo 18, seguidas de cómo deberían verse las secciones después de implementar los cambios anteriores, con la mayor parte del código nuevo de varios recursos de Pub/Sub:
ANTES:
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__)
DESPUÉS:
from flask import Flask, render_template, request
import google.auth
from google.cloud import ndb, pubsub
LIMIT = 10
TASKS = 1000
TOPIC = 'pullq'
SBSCR = 'worker'
app = Flask(__name__)
ds_client = ndb.Client()
ppc_client = pubsub.PublisherClient()
psc_client = pubsub.SubscriberClient()
_, PROJECT_ID = google.auth.default()
TOP_PATH = ppc_client.topic_path(PROJECT_ID, TOPIC)
SUB_PATH = psc_client.subscription_path(PROJECT_ID, SBSCR)
Visitar las actualizaciones de modelos de datos
El modelo de datos de Visit
no cambia. El acceso a Datastore requiere el uso explícito de ds_client.context()
, el administrador de contexto del cliente de la API de Cloud NDB. En el código, esto significa que unes las llamadas de Datastore en store_visit()
y fetch_visits()
dentro de los bloques with
de Python. Esta actualización es idéntica a la que se aborda en el módulo 2.
El cambio más relevante para Pub/Sub es reemplazar la puesta en cola de una tarea de extracción de la lista de tareas en cola con la publicación de un mensaje de Pub/Sub en el tema pullq
. A continuación, se muestra el código antes y después de realizar estas actualizaciones:
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 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)
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'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
ppc_client.publish(TOP_PATH, remote_addr.encode('utf-8'))
def fetch_visits(limit):
'get most recent visits'
with ds_client.context():
return Visit.query().order(-Visit.timestamp).fetch(limit)
Actualizaciones del modelo de datos de VisitorCount
El modelo de datos VisitorCount
no cambia y realiza fetch_counts()
, excepto por unir la consulta de Datastore dentro de un bloque with
, como se ilustra a continuación:
ANTES:
class VisitorCount(ndb.Model):
visitor = ndb.StringProperty(repeated=False, required=True)
counter = ndb.IntegerProperty()
def fetch_counts(limit):
'get top visitors'
return VisitorCount.query().order(-VisitorCount.counter).fetch(limit)
DESPUÉS:
class VisitorCount(ndb.Model):
visitor = ndb.StringProperty(repeated=False, required=True)
counter = ndb.IntegerProperty()
def fetch_counts(limit):
'get top visitors'
with ds_client.context():
return VisitorCount.query().order(-VisitorCount.counter).fetch(limit)
Actualiza el código del trabajador
El código del trabajador se actualiza, ya que reemplaza NBS por Cloud NDB y lista de tareas en cola con Pub/Sub, pero el flujo de trabajo sigue siendo el mismo.
- Une llamadas de Datastore en el bloque
with
del administrador de contexto de Cloud NDB. - La limpieza de lista de tareas en cola implica borrar todas las tareas de la lista de extracción. Con Pub/Sub, “ID de confirmación de recepción” se recopilan en
acks
y, luego, se borran o confirman. - Las tareas de extracción de la lista de tareas en cola se asignan de forma similar a como se extraen los mensajes de Pub/Sub. Si bien la eliminación de las tareas de extracción se realiza con los objetos de la tarea, los mensajes de Pub/Sub se borran a través de sus IDs de confirmación de recepción.
- Las cargas útiles de mensajes de Pub/Sub requieren bytes (no cadenas de Python), por lo que hay cierta codificación y decodificación UTF-8 cuando se publican y se extraen mensajes de un tema, respectivamente.
Reemplaza log_visitors()
por el siguiente código actualizado que implementa los cambios que se describen:
ANTES:
@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))
DESPUÉS:
@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 = {}
acks = set()
rsp = psc_client.pull(subscription=SUB_PATH, max_messages=TASKS)
msgs = rsp.received_messages
for rcvd_msg in msgs:
acks.add(rcvd_msg.ack_id)
visitor = rcvd_msg.message.data.decode('utf-8')
tallies[visitor] = tallies.get(visitor, 0) + 1
if acks:
psc_client.acknowledge(subscription=SUB_PATH, ack_ids=acks)
try:
psc_client.close()
except AttributeError: # special handler for grpcio<1.12.0
pass
# increment those counts in Datastore and return
if tallies:
with ds_client.context():
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(msgs), len(tallies))
No hay cambios en el controlador de la aplicación principal root()
. Tampoco se necesitan cambios en el archivo de plantilla HTML, templates/index.html
, por lo que esto une todas las actualizaciones necesarias. Felicitaciones por llegar a tu nueva aplicación del Módulo 19 con Cloud Pub/Sub.
7. Resumen/limpieza
Implementa tu app para verificar que funcione según lo previsto y en cualquier resultado reflejado. Ejecuta también el trabajador para procesar los recuentos 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 creado el tema pullq
y la suscripción worker
. 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 18, excepto que reemplazaste correctamente todo el mecanismo de cola subyacente:
El frontend web de la app ahora verifica que esta parte de la aplicación funciona. Si bien esta parte de la app consulta y muestra con éxito los visitantes principales y las visitas más recientes, recuerda que la app registra esta visita junto con la creación de una tarea de extracción para agregar a este visitante al recuento general. La tarea ahora está en la cola a la espera de ser procesada.
Puedes ejecutarlo con un servicio de backend de App Engine, un trabajo cron
, navegar a /log
o emitir una solicitud HTTP de línea de comandos. A continuación, se muestra una ejecución de ejemplo y una llamada al código del trabajador por curl
(sustituye 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.
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:
- Los diferentes componentes de Cloud Pub/Sub tienen un nivel gratuito. determina tu uso general para tener una mejor idea de las implicaciones de los costos y consulta la página de precios para obtener más detalles.
- 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
Más allá de este instructivo, otros módulos de migración que se enfocan en alejarse de los servicios en paquetes heredados que se deben considerar incluyen los siguientes:
- Módulo 2: migrar de
ndb
de App Engine a Cloud NDB - Módulos del 7 al 9: Migra de la lista de tareas en cola de App Engine (tareas push) a Cloud Tasks
- Módulos del 12 al 13: Migra de Memcache de App Engine a Cloud Memorystore
- Módulos del 15 al 16: Migra de Blobstore de App Engine a Cloud Storage
App Engine ya no es la única plataforma sin servidores en Google Cloud. Si tienes una aplicación pequeña de App Engine o una con funcionalidad limitada y deseas convertirla en un microservicio independiente, o si deseas dividir una aplicación monolítica en varios componentes reutilizables, estas son buenas razones para considerar cambiar a Cloud Functions. Si la creación de contenedores se volvió parte del flujo de trabajo de desarrollo de tu aplicación, en especial si consta de una canalización de CI/CD (integración continua/entrega o implementación continuas), considera migrar a Cloud Run. Estas situaciones se abordan en los siguientes módulos:
- Migra de App Engine a Cloud Functions: consulta el Módulo 11.
- Migra de App Engine a Cloud Run. Consulta el Módulo 4 para alojar tu app en contenedores con Docker, o el Módulo 5 para hacerlo sin contenedores, conocimiento sobre Docker ni
Dockerfile
.
Cambiar a otra plataforma sin servidores es opcional, y te recomendamos que consideres las mejores opciones para tus apps y casos de uso antes de realizar cualquier cambio.
Independientemente del módulo de migración que consideres a continuación, puedes acceder a todo el contenido de Serverless Migration Station (codelabs, videos, código fuente [si está disponible]) a través de su repositorio de código abierto. El README
del repositorio también proporciona orientación sobre qué migraciones considerar y cualquier "orden" relevante. de los módulos de migración.
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 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, encontrarás los vínculos a las carpetas del repositorio del módulo 18 (START) y el módulo 19 (FINISH).
Codelab | Python 2 | Python 3 |
(n/a) | ||
Módulo 19 (este codelab) | (igual que Python 2, excepto que use app3.yaml, a menos que haya actualizado app.yaml como se explicó anteriormente) |
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
Cloud Pub/Sub
- Página de producto de Cloud Pub/Sub
- Usa bibliotecas cliente de Pub/Sub
- Muestras de la biblioteca cliente de Pub/Sub para Python
- Documentación de la biblioteca cliente de Pub/Sub para Python
- Crear y Administrar temas de Pub/Sub
- Lineamientos para la asignación de nombres de temas de Pub/Sub
- Crear y administrar suscripciones a Pub/Sub
- App de ejemplo de App Engine (flexible) (también se puede implementar en el nivel Estándar; Python 3)
- Repositorio para la app de ejemplo anterior
- Suscripciones de extracción de Pub/Sub
- Suscripciones de envío de Pub/Sub
- App de muestra de envío de Pub/Sub de App Engine (Python 3)
- Repositorio de aplicación de muestra de envío de Pub/Sub de App Engine
- Información de precios de Pub/Sub
- ¿Cloud Tasks o Cloud Pub/Sub? (push frente a extracción)
App Engine NDB y Cloud NDB (Datastore)
- Documentación de App Engine NDB
- Repositorio de App Engine NDB
- Documentos de NDB de Google Cloud
- Repositorio de NDB de Google Cloud
- Información de precios de Cloud Datastore
Plataforma de App Engine
- Documentación de App Engine
- Entorno de ejecución de App Engine (entorno estándar) para Python 2
- Usa las bibliotecas integradas de App Engine en Python 2 de App Engine
- 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)
- Comparación primero y plataformas de segunda generación
- Asistencia a largo plazo para entornos de ejecución heredados
- Ejemplos de migración de documentación
- Ejemplos de migración aportados por la comunidad
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.