Migra de Memcache de App Engine a Cloud Memorystore (módulo 13)

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 de Memcache de App Engine a Cloud Memorystore (para Redis). También hay una migración implícita de ndb de App Engine a Cloud NDB, pero se trata principalmente en el codelab del módulo 2. echa un vistazo para obtener más información paso a paso.

En un próximo lab,

  • Configura una instancia de Cloud Memorystore (desde la consola de Cloud o la herramienta de gcloud)
  • Configura un conector de Acceso a VPC sin servidores de Cloud (desde Cloud Console o la herramienta de gcloud)
  • Migra de App Engine Memcache a Cloud Memorystore
  • Implementar el almacenamiento en caché con Cloud Memorystore en una app de muestra
  • Migra de App Engine ndb a Cloud NDB

Requisitos

Encuesta

¿Cómo usarás este instructivo?

Solo leerlo Léelo y completa los ejercicios. .

¿Cómo calificarías tu experiencia en Python?

Principiante Intermedio Avanzado

¿Cómo calificarías tu experiencia en el uso de los servicios de Google Cloud?

Principiante Intermedio Avanzado .
.

2. Información general

En este codelab, se muestra cómo migrar una app de ejemplo de Memcache de App Engine (y NDB) a Cloud Memorystore (y Cloud NDB). Este proceso implica reemplazar las dependencias de los paquetes de servicios de App Engine, lo que hace que tus apps sean más portátiles. Puedes optar por permanecer en App Engine o considerar cambiar a cualquiera de las alternativas descritas anteriormente.

Esta migración requiere más esfuerzo que las demás de esta serie. El reemplazo recomendado de Memcache de App Engine es Cloud Memorystore, un servicio de almacenamiento en caché completamente administrado y basado en la nube. Memorystore admite dos motores populares de almacenamiento en caché de código abierto, Redis y Memcached. En este módulo de migración, se usa Cloud Memorystore para Redis. Puedes obtener más información en la Descripción general de Memorystore y Redis.

Debido a que Memorystore requiere un servidor en ejecución, también se necesita Cloud VPC. Específicamente, debe crearse un conector de Acceso a VPC sin servidores para que la app de App Engine pueda conectarse a la instancia de Memorystore a través de su dirección IP privada. Cuando hayas completado este ejercicio, habrás actualizado la app para que, si bien se comporte como antes, Cloud Memorystore sea el servicio de almacenamiento en caché y reemplace el servicio Memcache de App Engine.

Este instructivo comienza con la app de ejemplo del módulo 12 en Python 2 seguida de una actualización menor adicional, opcional y menor a Python 3. Si ya sabes acceder a los servicios empaquetados de App Engine desde Python 3 mediante el SDK de App Engine para Python 3, puedes comenzar con la versión de Python 3 de la app de ejemplo del Módulo 12. En ese caso, se quitará el uso del SDK, ya que Memorystore no es un servicio empaquetado de App Engine. Aprender a usar el SDK de Python 3 para App Engine está fuera del alcance de este instructivo.

En este instructivo, se presentan los siguientes pasos clave:

  1. Configuración y trabajo previo
  2. Configura servicios de almacenamiento en caché
  3. Actualiza archivos de configuración
  4. Actualizar la aplicación principal

3. Configuración y trabajo previo

Prepara un proyecto de Cloud

Te recomendamos que vuelvas a usar el mismo proyecto que usaste para completar el codelab del módulo 12. Como alternativa, puedes crear un proyecto completamente nuevo o reutilizar otro proyecto existente. Cada codelab de esta serie tiene un "COMENZAR" (el código de referencia desde el que comenzar) y "FINALIZAR" (la app migrada). Te proporcionamos el código FINISH para que puedas comparar tus soluciones con las nuestras en caso de que tengas problemas. Siempre puedes revertir a START si algo sale mal. Estos puntos de control están diseñados para garantizar que puedas aprender a realizar las migraciones con éxito.

Sin importar el proyecto de Cloud que uses, asegúrate de tener una cuenta de facturación activa. Además, asegúrate de que App Engine esté habilitado. Revisa y asegúrate de comprender las implicaciones de los costos generales relacionadas con estos instructivos. Sin embargo, a diferencia de otros de esta serie, en este codelab se usan recursos de Cloud que no tienen un nivel gratuito, por lo que se generarán algunos costos para completar el ejercicio. Se proporcionará información más específica sobre los costos junto con recomendaciones para reducir el uso, incluidas instrucciones al final sobre la liberación de recursos para minimizar los cargos de facturación.

Obtén app de ejemplo del modelo de referencia

A partir del código de referencia del módulo 12 desde el que comenzamos, este codelab te guiará paso a paso a través de la migración. Cuando termines, llegarás a una app del módulo 13 que funcione y se parecerá mucho al código de una de las carpetas FINISH. Estos son esos recursos:

La carpeta START debe contener los siguientes archivos:

$ ls
README.md               app.yaml                main.py                 requirements.txt        templates                

Si comienzas desde la versión de Python 2, también habrá un archivo appengine_config.py y, posiblemente, una carpeta lib si completaste el codelab del módulo 12.

(Re)Implementa la app del Módulo 12

Pasos previos restantes:

  1. Vuelve a familiarizarte con la herramienta de línea de comandos de gcloud (si es necesario)
  2. (Vuelve a implementar el código del módulo 12 en App Engine (si es necesario)

Los usuarios de Python 2 deben borrar y reinstalar la carpeta lib con estos comandos:

rm -rf ./lib; pip install -t lib -r requirements.txt                

Ahora todos (usuarios de Python 2 y 3) deberían subir el código a App Engine con este comando:

gcloud app deploy                

Una vez implementada correctamente, confirma que la app se vea y funcione como la app en el módulo 12, una app web que hace un seguimiento de las visitas y las almacena en caché para el mismo usuario durante una hora:

dfe56a02ae59ddd8.png

Debido a que las visitas más recientes se almacenan en caché, las actualizaciones de la página deberían cargarse con bastante rapidez.

4. Configura servicios de almacenamiento en caché

Cloud Memorystore no es un servicio sin servidores. Se requiere una instancia. en este caso, uno ejecuta Redis. A diferencia de Memcache, Memorystore es un producto independiente de Cloud y no tiene un nivel gratuito, así que asegúrate de consultar la información de precios de Memorystore para Redis antes de continuar. Para minimizar los costos de este ejercicio, recomendamos la menor cantidad de recursos para operar: un nivel de servicio Básico y una capacidad de 1 GB.

La instancia de Memorystore está en una red diferente a la de tu app de App Engine (instancias), por lo que se debe crear un conector de Acceso a VPC sin servidores para que App Engine pueda acceder a tus recursos de Memorystore. Para minimizar los costos de VPC, elige el tipo de instancia (f1-micro) y la menor cantidad de instancias que desees solicitar (sugerimos un mínimo 2 y máximo 3). Consulta también la página de información de precios de VPC.

Repetimos estas recomendaciones para reducir los costos mientras te guíamos en la creación de cada recurso necesario. Además, cuando crees recursos de Memorystore y VPC en la consola de Cloud, verás la calculadora de precios de cada producto en la esquina superior derecha, lo que te proporcionará una estimación del costo mensual (consulta la siguiente ilustración). Esos valores se ajustan automáticamente si cambias tus opciones. A grandes rasgos, esto es lo que deberías esperar ver:

7eb35ebf7248c010.png

Ambos recursos son obligatorios y no importa cuál crees primero. Si creas primero la instancia de Memorystore, la app de App Engine no podrá acceder a ella sin el conector de VPC. Del mismo modo, si creas primero el conector de VPC, no habrá nada en esa red de VPC con la que tu aplicación de App Engine pueda comunicarse. En este instructivo, primero creas la instancia de Memorystore y, luego, sigue el conector de VPC.

Una vez que ambos recursos estén en línea, agregarás la información relevante a app.yaml para que tu app pueda acceder a la caché. También puedes consultar las guías de Python 2 o Python 3 en la documentación oficial. También vale la pena consultar la guía de almacenamiento en caché de datos de la página de migración de Cloud NDB ( Python 2 o Python 3).

Crea una instancia de Cloud Memorystore

Debido a que Cloud Memorystore no tiene un nivel gratuito, recomendamos asignar la menor cantidad de recursos para completar el codelab. Puedes mantener los costos al mínimo con estos parámetros de configuración:

  • Selecciona el nivel de servicio más bajo: Básico (predeterminado en la consola: “Estándar”; gcloud predeterminado: “Básico”).
  • Elige la cantidad mínima de almacenamiento: 1 GB (valor predeterminado de la consola: 16 GB; valor predeterminado de gcloud: 1 GB).
  • Por lo general, las versiones más recientes de cualquier software requieren la mayor cantidad de recursos, pero probablemente no se recomienda seleccionar la versión más antigua. La segunda versión más reciente es la versión de Redis 5.0 (configuración predeterminada de la consola: 6.x).

Con esos parámetros de configuración en mente, la siguiente sección te guiará en la creación de la instancia desde la consola de Cloud. Si prefieres hacerlo desde la línea de comandos, omite este paso.

Desde la consola de Cloud

Ve a la página de Cloud Memorystore en la consola de Cloud (es posible que se te soliciten datos de facturación). Si aún no habilitas Memorystore, se te solicitará que lo hagas:

68318997e3105db6.png

Una vez que la hayas habilitado (y posiblemente junto con la facturación), llegarás al panel de Memorystore. Aquí puedes ver todas las instancias que se crearon en tu proyecto. El proyecto que se muestra a continuación no tiene ninguno, por eso ves "No hay filas para mostrar". Para crear una instancia de Memorystore, haz clic en Crear instancia en la parte superior:

63547aa575838a36.png

En esta página, se incluye un formulario que debes completar con la configuración deseada para crear la instancia de Memorystore:

b77d927287fdf4c7.png

Para mantener los costos bajos para este instructivo y su app de ejemplo, sigue las recomendaciones que mencionamos anteriormente. Luego de realizar tus selecciones, haz clic en Crear. El proceso de creación tarda varios minutos. Cuando finalice, copia la dirección IP y el número de puerto de la instancia para agregarlos a app.yaml.

Desde la línea de comandos

Aunque es visualmente informativo crear instancias de Memorystore desde la consola de Cloud, algunas prefieren la línea de comandos. Antes de continuar, asegúrate de que gcloud esté instalado e inicializado.

Al igual que con la consola de Cloud, se debe habilitar Cloud Memorystore para Redis. Ejecuta el comando gcloud services enable redis.googleapis.com y espera a que se complete, como en este ejemplo:

$ gcloud services enable redis.googleapis.com
Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.

Si ya se habilitó el servicio, ejecutar el comando (de nuevo) no tiene efectos secundarios (negativos). Con el servicio habilitado, crearemos una instancia de Memorystore. Ese comando se ve de la siguiente manera:

gcloud redis instances create NAME --redis-version VERSION \
    --region REGION --project PROJECT_ID

Elige un nombre para tu instancia de Memorystore. en este lab se usa “demo-ms” como el nombre, junto con un ID del proyecto de "my-project". La región de esta app de ejemplo es us-central1 (igual que us-central), pero puedes usar una más cercana si la latencia es un problema. Debes seleccionar la misma región que tu aplicación de App Engine. Puedes seleccionar la versión de Redis que prefieras, pero estamos usando la versión 5, como se recomendó anteriormente. Dada esa configuración, este es el comando que usarías (junto con el resultado asociado):

$ gcloud redis instances create demo-ms --region us-central1 \
    --redis-version redis_5_0 --project my-project

Create request issued for: [demo-ms]
Waiting for operation [projects/my-project/locations/us-central1/operations/operation-xxxx] to complete...done.
Created instance [demo-ms].

A diferencia de la configuración predeterminada de la consola de Cloud, la configuración predeterminada de gcloud es mínima. El resultado es que para ese comando no se requerían el nivel de servicio ni la cantidad de almacenamiento. Crear una instancia de Memorystore tarda varios minutos. Cuando esté listo, ten en cuenta la dirección IP y el número de puerto de la instancia, ya que pronto se agregarán a app.yaml.

Confirma que se creó la instancia

Desde la consola de Cloud o la línea de comandos

Ya sea que hayas creado tu instancia desde la consola de Cloud o desde la línea de comandos, puedes confirmar que está disponible y lista para usarse con este comando: gcloud redis instances list --region REGION

Este es el comando para verificar las instancias en la región us-central1, junto con el resultado esperado que muestra la instancia que acabamos de crear:

$ gcloud redis instances list --region us-central1
INSTANCE_NAME  VERSION    REGION       TIER   SIZE_GB  HOST         PORT  NETWORK  RESERVED_IP     STATUS  CREATE_TIME
demo-ms        REDIS_5_0  us-central1  BASIC  1        10.aa.bb.cc  6379  default  10.aa.bb.dd/29  READY   2022-01-28T09:24:45

Cuando se te solicite la información de la instancia o para configurar tu app, asegúrate de usar HOST y PORT (no RESERVED_IP). El panel de Cloud Memorystore en la consola de Cloud ahora debería mostrar esa instancia:

c5a6948ec1c056ed.png

Desde la máquina virtual de Compute Engine

Si tienes una máquina virtual (VM) de Compute Engine, también puedes enviar comandos directos de la instancia de Memorystore desde una VM para confirmar que funciona. Ten en cuenta que el uso de una VM puede tener costos asociados, independientemente de los recursos que ya estés usando.

Crear conector de Acceso a VPC sin servidores

Al igual que con Cloud Memorystore, puedes crear el conector de Cloud VPC sin servidores en la consola de Cloud o en la línea de comandos. De manera similar, Cloud VPC no tiene un nivel gratuito, por lo que recomendamos asignar la menor cantidad de recursos para completar el codelab a fin de reducir al mínimo los costos. Esto se puede lograr con la siguiente configuración:

  • Selecciona la cantidad máxima de instancias más baja: 3 (la consola y gcloud son las predeterminadas: 10).
  • Elige el tipo de máquina de menor costo: f1-micro (configuración predeterminada de la consola: e2-micro, no gcloud predeterminada)

En la siguiente sección, se explica cómo crear el conector desde la consola de Cloud con la configuración de VPC de Cloud anterior. Si prefieres hacerlo desde la línea de comandos, pasa a la siguiente sección.

Desde la consola de Cloud

Dirígete a Cloud Networking “Acceso a VPC sin servidores” en la consola de Cloud (es posible que se te soliciten los datos de facturación). Si aún no has habilitado la API, se te solicitará que lo hagas:

e3b9c0651de25e97.png

Una vez que habilites la API (y posiblemente junto con la facturación), llegarás al panel en el que se muestran todos los conectores de VPC creados. El proyecto que se usó en la siguiente captura de pantalla no tiene ninguno, por eso dice: "No hay filas para mostrar". En tu consola, haz clic en Crear conector en la parte superior:

b74b49b9d73b7dcf.png

Completa el formulario con la configuración deseada:

6b26b2aafa719f73.png

Elige la configuración apropiada para tus propias aplicaciones. Para este instructivo y su app de ejemplo con necesidades mínimas, tiene sentido minimizar los costos, así que sigue las recomendaciones que mencionamos anteriormente. Una vez que hayas realizado tus selecciones, haz clic en Crear. La solicitud de un conector de VPC tardará unos minutos en completarse.

Desde la línea de comandos

Antes de crear un conector de VPC, habilita la API de Acceso a VPC sin servidores. Deberías ver un resultado similar después de ejecutar el siguiente comando:

$ gcloud services enable vpcaccess.googleapis.com
Operation "operations/acf.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.

Con la API habilitada, se crea un conector de VPC con un comando que se ve de la siguiente manera:

gcloud compute networks vpc-access connectors create CONNECTOR_NAME \
    --range 10.8.0.0/28 --region REGION --project PROJECT_ID

Elige un nombre para tu conector y una dirección IP de inicio del bloque de CIDR /28 sin usar. En este instructivo, se hacen las siguientes suposiciones:

  • Project ID (ID del proyecto): my-project
  • Nombre del conector de VPC: demo-vpc
  • Cantidad mínima de instancias: 2 (predeterminado) y máx. de instancias: 3
  • Tipo de instancia: f1-micro
  • Región: us-central1
  • Bloque CIDR de IPv4: 10.8.0.0/28 (como se recomienda en la consola de Cloud)

Si ejecutas el comando con las suposiciones anteriores en mente, puedes obtener un resultado similar al que se muestra a continuación:

$ gcloud compute networks vpc-access connectors create demo-vpc \
    --max-instances 3 --range 10.8.0.0/28 --machine-type f1-micro \
    --region us-central1  --project my-project

Create request issued for: [demo-vpc]
Waiting for operation [projects/my-project/locations/us-central1/operations/xxx] to complete...done.
Created connector [demo-vpc].

El comando anterior omite la especificación de valores predeterminados, como la cantidad mínima de instancias de 2 y una red llamada default. La creación de un conector de VPC tarda varios minutos en completarse.

Confirma que se creó el conector

Una vez que se haya completado el proceso, ejecuta el siguiente comando gcloud, suponiendo que es la región us-central1, para confirmar que se creó y que está listo para usarse:

$ gcloud compute networks vpc-access connectors list --region us-central1
CONNECTOR_ID  REGION       NETWORK  IP_CIDR_RANGE  SUBNET  SUBNET_PROJECT  MIN_THROUGHPUT  MAX_THROUGHPUT  STATE
demo-vpc      us-central1  default  10.8.0.0/28                            200             300             READY

De manera similar, el panel ahora debería mostrar el conector que acabas de crear:

e03db2c8140ed014.png

Toma nota del ID del proyecto de Cloud, el nombre del conector de VPC y la región.

Ahora que creaste los recursos adicionales de Cloud necesarios, ya sea mediante la línea de comandos o en la consola, es momento de actualizar la configuración de la aplicación para admitir su uso.

5. Actualiza archivos de configuración

El primer paso es realizar todas las actualizaciones necesarias en los archivos de configuración. El objetivo principal de este codelab es ayudar a los usuarios de Python 2 a migrar. Sin embargo, el seguimiento del contenido suele incluir información sobre la portabilidad a Python 3 en cada sección que aparece a continuación.

requirements.txt

En esta sección, agregamos paquetes para admitir Cloud Memorystore y Cloud NDB. En el caso de Cloud Memorystore para Redis, es suficiente usar el cliente estándar de Redis para Python (redis), ya que no hay una biblioteca cliente de Cloud Memorystore en sí. Agrega redis y google-cloud-ndb a requirements.txt, uniéndote a flask del módulo 12:

flask
redis
google-cloud-ndb

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, especifica los números de versión para bloquear las versiones de trabajo.

app.yaml

Nuevas secciones para agregar

El entorno de ejecución de App Engine para Python 2 requiere paquetes de terceros específicos cuando se usan las API de Cloud, como Cloud NDB, es decir, grpcio y setuptools. Los usuarios de Python 2 deben enumerar las bibliotecas integradas como estas junto con una versión disponible en app.yaml. Si aún no tienes una sección libraries, crea una y agrega ambas bibliotecas como se muestra a continuación:

libraries:
- name: grpcio
  version: latest
- name: setuptools
  version: latest

Cuando migres tu app, es posible que ya tenga una sección libraries. Si es así, y faltan grpcio y setuptools, solo agrégalos a tu sección libraries existente.

Luego, nuestra app de ejemplo necesita la instancia de Cloud Memorystore y la información del conector de VPC, por lo que debes agregar las siguientes dos secciones nuevas a app.yaml, sin importar qué entorno de ejecución de Python uses:

env_variables:
    REDIS_HOST: 'YOUR_REDIS_HOST'
    REDIS_PORT: 'YOUR_REDIS_PORT'

vpc_access_connector:
    name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR

Eso es todo con respecto a las actualizaciones requeridas. Tu app.yaml actualizado debería verse de la siguiente manera:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

libraries:
- name: grpcio
  version: 1.0.0
- name: setuptools
  version: 36.6.0

env_variables:
    REDIS_HOST: 'YOUR_REDIS_HOST'
    REDIS_PORT: 'YOUR_REDIS_PORT'

vpc_access_connector:
    name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR

A continuación, se muestra un "antes y después" Con ejemplos de las actualizaciones que debes aplicar a app.yaml:

ec2bb027a67debb6.png

*Diferencias de Python 3

Esta sección es opcional y solo si tienes que realizar la portabilidad a Python 3. Para hacerlo, debes realizar una serie de cambios en la configuración de Python 2. Omite esta sección si no deseas realizar la actualización en este momento.

Ni threadsafe ni api_version se usan para el entorno de ejecución de Python 3, así que borra ambas opciones de configuración. El entorno de ejecución más reciente de App Engine no admite bibliotecas de terceros integradas ni la copia de bibliotecas no integradas. El único requisito para los paquetes de terceros es incluirlos en una lista en requirements.txt. Como resultado, se puede borrar toda la sección libraries de app.yaml.

Además, el entorno de ejecución de Python 3 requiere el uso de frameworks web que hagan su propio enrutamiento; por eso, les mostramos a los desarrolladores cómo migrar de webp2 a Flask en el módulo 1. Como resultado, todos los controladores de secuencia de comandos se deben cambiar a auto. Como esta app no entrega archivos estáticos, es "sin sentido" para tener controladores en la lista (ya que todos son auto), por lo que también se puede quitar toda la sección handlers. Como resultado, tu nuevo app.yaml abreviado ajustado para Python 3 debería acortarse de la siguiente manera:

runtime: python39

env_variables:
    REDIS_HOST: 'YOUR_REDIS_HOST'
    REDIS_PORT: 'YOUR_REDIS_PORT'

vpc_access_connector:
    name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR

A continuación, se resumen las diferencias en app.yaml cuando se realiza la portabilidad a Python 3:

  • Borrar los parámetros de configuración de threadsafe y api_version
  • Borrar la sección libraries
  • Borrar la sección handlers (o solo los controladores script si tu app entrega archivos estáticos)

Reemplaza los valores

Los valores de las secciones nuevas de Memorystore y el conector de VPC son solo marcadores de posición. Reemplaza esos valores en mayúscula (YOUR_REDIS_HOST, YOUR_REDIS_PORT, PROJECT_ID, REGION, CONNECTOR_NAME) por los valores guardados desde cuando creaste esos recursos anteriormente. Con respecto a tu instancia de Memorystore, asegúrate de usar HOST (no RESERVED_IP) y PORT. A continuación, se muestra una forma rápida de línea de comandos de obtener HOST y PORT, suponiendo que el nombre de instancia demo-ms y REGION es us-central1:

$ gcloud redis instances describe demo-ms --region us-central1 \
    --format "value(host,port)"
10.251.161.51   6379

Si la dirección IP de nuestra instancia de Redis de ejemplo era 10.10.10.10 con el puerto 6379 de nuestro proyecto my-project, ubicado en la región us-central1 con un nombre de conector de VPC de demo-vpc, estas secciones en app.yaml se verán de la siguiente manera:

env_variables:
    REDIS_HOST: '10.10.10.10'
    REDIS_PORT: '6379'

vpc_access_connector:
    name: projects/my-project/locations/us-central1/connectors/demo-vpc

Crea o actualiza appengine_config.py

Cómo agregar compatibilidad con bibliotecas de terceros integradas

Al igual que hicimos antes con app.yaml, agrega el uso de las bibliotecas grpcio y setuptools. Modifica appengine_config.py para que admita bibliotecas de terceros integradas. Si esto te resulta familiar, es porque también se requería en el módulo 2 cuando se migraba de ndb de App Engine a Cloud NBS. El cambio exacto requerido es agregar la carpeta lib al conjunto de trabajo setuptools.pkg_resources:

4140b3800694f77e.png

*Diferencias de Python 3

Esta sección es opcional y solo si tienes que realizar la portabilidad a Python 3. Uno de los bienvenidos cambios de segunda generación de App Engine es que ya no es necesario copiar (a veces denominada "proveedor") de paquetes de terceros (no integrados) ni hacer referencia a paquetes de terceros integrados en app.yaml, lo que significa que puedes borrar todo el archivo appengine_config.py.

6. Actualizar archivos de la aplicación

Solo hay un archivo de la aplicación, main.py, por lo que todos los cambios en esta sección afectan solo a ese archivo. Ofrecemos una representación visual de los cambios que haremos para migrar esta aplicación a Cloud Memorystore. Solo tiene fines ilustrativos y no pretende realizar un análisis minucioso. Todo el trabajo está en los cambios que hacemos en el código.

5d043768ba7be742.png

Veamos esto una sección a la vez, empezando por la parte superior.

Actualizar importaciones

La sección de importación en main.py para el módulo 12 usa Cloud NDB y Cloud Tasks. estas son sus importaciones:

ANTES:

from flask import Flask, render_template, request
from google.appengine.api import memcache
from google.appengine.ext import ndb

Para cambiar a Memorystore, es necesario leer las variables de entorno, por lo que necesitamos el módulo os de Python y redis, el cliente de Redis para Python. Dado que Redis no puede almacenar en caché objetos de Python, ordena la lista de visitas más recientes usando pickle, así que impórtalo también. Un beneficio de Memcache es que la serialización de objetos se produce automáticamente, mientras que Memorystore es algo más "DIY". Por último, actualiza de App Engine ndb a Cloud NBS reemplazando google.appengine.ext.ndb con google.cloud.ndb. Después de estos cambios, tus importaciones deberían verse de la siguiente manera:

DESPUÉS:

import os
import pickle
from flask import Flask, render_template, request
from google.cloud import ndb
import redis

Actualizar inicialización

La inicialización del módulo 12 consiste en crear una instancia del objeto de aplicación de Flask app y establecer una constante para una hora de almacenamiento en caché:

ANTES:

app = Flask(__name__)
HOUR = 3600

Para usar las APIs de Cloud, se necesita un cliente, así que crea una instancia de un cliente de Cloud NDB justo después de Flask. A continuación, obtén la dirección IP y el número de puerto de la instancia de Memorystore de las variables de entorno que configuraste en app.yaml. Con esa información, crea una instancia de un cliente de Redis. Así se verá tu código después de esas actualizaciones:

DESPUÉS:

app = Flask(__name__)
ds_client = ndb.Client()
HOUR = 3600
REDIS_HOST = os.environ.get('REDIS_HOST', 'localhost')
REDIS_PORT = os.environ.get('REDIS_PORT', '6379')
REDIS = redis.Redis(host=REDIS_HOST, port=REDIS_PORT)

*Migración de Python 3

Esta sección es opcional si estás comenzando desde la versión de Python 3 de la app del módulo 12. Si es así, hay varios cambios necesarios relacionados con las importaciones y la inicialización.

En primer lugar, dado que Memcache es un servicio empaquetado de App Engine, su uso en una app de Python 3 requiere el SDK de App Engine, en el que se debe unir específicamente la aplicación WSGI (además de otra configuración necesaria):

ANTES:

from flask import Flask, render_template, request
from google.appengine.api import memcache, wrap_wsgi_app
from google.appengine.ext import ndb

app = Flask(__name__)
app.wsgi_app = wrap_wsgi_app(app.wsgi_app)
HOUR = 3600

Debido a que estamos migrando a Cloud Memorystore (no un servicio empaquetado en App Engine como Memcache), se debe quitar el uso del SDK. Esto es sencillo, ya que solo borrarás toda la línea que importa memcache y wrap_wsgi_app. También borra la línea que llama a wrap_wsgi_app(). Estas actualizaciones dejan esta parte de la app (en realidad, la app completa) idéntica a la versión de Python 2.

DESPUÉS:

import os
import pickle
from flask import Flask, render_template, request
from google.cloud import ndb
import redis

app = Flask(__name__)
ds_client = ndb.Client()
HOUR = 3600
REDIS_HOST = os.environ.get('REDIS_HOST', 'localhost')
REDIS_PORT = os.environ.get('REDIS_PORT', '6379')
REDIS = redis.Redis(host=REDIS_HOST, port=REDIS_PORT)

Por último, quita el uso del SDK de app.yaml (borra la línea: app_engine_apis: true) y requirements.txt (borra la línea: appengine-python-standard).

Migra a Cloud Memorystore (y Cloud NDB)

El modelo de datos de Cloud NDB está diseñado para ser compatible con los ndb de App Engine, lo que significa que la definición de los objetos Visit es la misma. Para imitar la migración del módulo 2 a Cloud NDB, todas las llamadas de Datastore en store_visit() y fetch_visits() se aumentan y se incorporan en un nuevo bloque with (ya que se requiere el uso del administrador de contexto de Cloud NDB). Estas son esas llamadas antes del cambio:

ANTES:

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)

Agrega un bloque with ds_client.context() a ambas funciones y coloca las llamadas a Datastore dentro (con sangría). En este caso, no es necesario realizar cambios para las llamadas en sí:

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()

def fetch_visits(limit):
    'get most recent visits'
    with ds_client.context():
        return Visit.query().order(-Visit.timestamp).fetch(limit)

A continuación, veamos los cambios de almacenamiento en caché. Esta es la función main() del módulo 12:

ANTES:

@app.route('/')
def root():
    'main application (GET) handler'
    # check for (hour-)cached visits
    ip_addr, usr_agt = request.remote_addr, request.user_agent
    visitor = '{}: {}'.format(ip_addr, usr_agt)
    visits = memcache.get('visits')

    # register visit & run DB query if cache empty or new visitor
    if not visits or visits[0].visitor != visitor:
        store_visit(ip_addr, usr_agt)
        visits = list(fetch_visits(10))
        memcache.set('visits', visits, HOUR)  # set() not add()

    return render_template('index.html', visits=visits)

Redis tiene la función "get" y "establecer" al igual que Memcache. Todo lo que hacemos es intercambiar las respectivas bibliotecas cliente, ¿verdad? Estuviste cerca. Como se mencionó antes, no podemos almacenar en caché una lista de Python con Redis (porque primero debe serializarse, algo que Memcache se encarga automáticamente), por lo tanto, en la llamada a set(), "pickle" las visitas en una cadena con pickle.dumps(). Del mismo modo, cuando recuperes las visitas de la caché, deberás desenmarañarlas con pickle.loads() justo después de get(). A continuación, se muestra el controlador principal después de implementar esos cambios:

DESPUÉS:

@app.route('/')
def root():
    'main application (GET) handler'
    # check for (hour-)cached visits
    ip_addr, usr_agt = request.remote_addr, request.user_agent
    visitor = '{}: {}'.format(ip_addr, usr_agt)
    rsp = REDIS.get('visits')
    visits = pickle.loads(rsp) if rsp else None

    # register visit & run DB query if cache empty or new visitor
    if not visits or visits[0].visitor != visitor:
        store_visit(ip_addr, usr_agt)
        visits = list(fetch_visits(10))
        REDIS.set('visits', pickle.dumps(visits), ex=HOUR)

    return render_template('index.html', visits=visits)

Con esto concluye los cambios requeridos en main.py para convertir el uso de Memcache de la app de ejemplo en Cloud Memorystore. ¿Qué ocurre con la plantilla HTML y la portabilidad a Python 3?

¿Quieres actualizar el archivo de plantilla HTML y el puerto a Python 3?

¡Sorpresa! No hay nada que hacer aquí, ya que la aplicación se diseñó para ejecutarse tanto en Python 2 como en Python 3 sin cambios en el código ni bibliotecas de compatibilidad. Encontrarás main.py. idéntico en mod13a (2.x) y mod13b (3.x) "FINISH" individuales. Lo mismo ocurre con requirements.txt , excepto por las diferencias en los números de versión (si se usan). Como la interfaz de usuario permanece igual, templates/index.html tampoco se actualiza.

Todo lo necesario para ejecutar esta app en Python 3 de App Engine se completó antes en la configuración: se quitaron directivas innecesarias de app.yaml y se borraron las carpetas appengine_config.py y lib, ya que no se usan en Python 3.

7. 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. Después de validar la app, realiza una limpieza y considera los pasos siguientes.

Implementa y verifica la aplicación

La última verificación es siempre implementar la app de ejemplo. Si eres desarrollador de Python 2, borra y reinstala lib con los siguientes comandos. (Si tienes Python 2 y 3 instalados en tu sistema, es posible que debas ejecutar pip2 de manera explícita en su lugar).

rm -rf ./lib
pip install -t lib -r requirements.txt

Tanto los desarrolladores de Python 2 como los de Python 3 ahora deberían implementar sus aplicaciones con lo siguiente:

gcloud app deploy

Como simplemente reorganizaste los elementos internos para un servicio de almacenamiento en caché completamente diferente, la app debería funcionar de manera idéntica a la del Módulo 12:

App de visitme del módulo 7

Con este paso se completa el codelab. Te invitamos a comparar tu app de ejemplo actualizada con cualquiera de las carpetas del Módulo 13: mod13a (Python 2) o mod13b (Python 3).

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:

En este instructivo, se incluyó el uso de cuatro productos de Cloud:

  • App Engine
  • Cloud Datastore
  • Cloud Memorystore
  • VPC de Cloud

A continuación, se incluyen instrucciones para liberar estos recursos y evitar o minimizar los cargos de facturación.

Cierra la instancia de Memorystore y el conector de VPC

Estos son los productos sin un nivel gratuito, por lo que estás generando facturación en este momento. Si no cierras tu proyecto de Cloud (consulta la siguiente sección), debes borrar tanto tu instancia de Memorystore como el conector de VPC para detener la facturación. Al igual que cuando creaste estos recursos, también puedes liberarlos desde la consola de Cloud o desde la línea de comandos.

Desde la consola de Cloud

Para borrar la instancia de Memorystore, vuelve al panel de Memorystore y haz clic en el ID de la instancia:

2b09baf1aa2e0a25.png

Cuando estés en la página de detalles de la instancia, haz clic en “Borrar”. y confirma lo siguiente:

f9d9eb1c1d4c6107.png

Para borrar el conector de VPC, ve a su panel, selecciona la casilla de verificación junto al conector que deseas borrar y, luego, haz clic en “Borrar” y confirma lo siguiente:

ca5fbd9f4c7c9b60.png

Desde la línea de comandos

Con el siguiente par de comandos de gcloud, se borran la instancia de Memorystore y el conector de VPC, respectivamente:

  • gcloud redis instances delete INSTANCE --region REGION
  • gcloud compute networks vpc-access connectors delete CONNECTOR --region REGION

Si no configuraste tu ID del proyecto con gcloud config set project, es posible que debas proporcionar --project PROJECT_ID. Si tu instancia de Memorystore se llama demo-ms y el conector de VPC se llama demo-vpc, y ambos se encuentran en la región us-central1, emite el siguiente par de comandos y confirma lo siguiente:

$ gcloud redis instances delete demo-ms --region us-central1
You are about to delete instance [demo-ms] in [us-central1].
Any associated data will be lost.

Do you want to continue (Y/n)?

Delete request issued for: [demo-ms]
Waiting for operation [projects/PROJECT/locations/REGION/operations/operation-aaaaa-bbbbb-ccccc-ddddd] to complete...done.
Deleted instance [demo-ms].
$
$ gcloud compute networks vpc-access connectors delete demo-vpc --region us-central1
You are about to delete connector [demo-vpc] in [us-central1].
Any associated data will be lost.

Do you want to continue (Y/n)?

Delete request issued for: [demo-vpc]
Waiting for operation [projects/PROJECT/locations/REGION/operations/aaaaa-bbbb-cccc-dddd-eeeee] to complete...done.
Deleted connector [demo-vpc].

Cada solicitud tarda unos minutos en ejecutarse. Estos pasos son opcionales si decides cerrar todo el proyecto de Cloud como se describió antes. Sin embargo, se te seguirá cobrando hasta que se complete el proceso de cierre.

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:

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 de repo del Módulo 12 (COMENZAR) y Módulo 13 (FINALIZAR). También puedes acceder a ellos desde el repositorio para todas las migraciones del codelab de App Engine. Puedes clonar o descargar un archivo ZIP.

Codelab

Python 2

Python 3

Módulo 12

código

código

Módulo 13 (este codelab)

código

código

Referencias en línea

A continuación, hay recursos en línea que pueden ser relevantes para este tutorial:

App Engine

App Engine NDB y Cloud NDB

Memcache de App Engine y Cloud Memorystore

VPC de Cloud

Otra información de Cloud

Licencia

Este trabajo cuenta con una licencia Atribución 2.0 Genérica de Creative Commons.