Módulo 2: Migra de App Engine NDB a Cloud NDB

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.

En este instructivo, aprenderás a migrar de la biblioteca cliente ndb (Next Database) de App Engine a la biblioteca cliente de Cloud NDB.

Obtendrás información para hacer las siguientes acciones

  • Usa la biblioteca de ndb de App Engine (si no estás familiarizado con ella).
  • Migra de ndb a Cloud NDB
  • Migra más tu app a Python 3

Qué necesitará

Encuesta

¿Cómo usarás este codelab?

Solo te recomendamos que lo leas Léelo y completa los ejercicios

En el módulo 1, migraremos los frameworks web de webapp2 integrado de App Engine a Flask. En este codelab, continuaremos con los servicios integrados de App Engine y cambiaremos de la biblioteca ndb de App Engine a Cloud NDB de Google.

Una vez completada la migración, puedes hacer lo siguiente:

  1. Migra a Python 3 y al entorno de ejecución de App Engine de última generación
  2. Migra a Cloud Datastore (biblioteca cliente para apps que no son de App Engine)
  3. Crea contenedores en tu aplicación de Python 2 (o 3) y migra a Cloud Run.
  4. Agrega el uso de listas de tareas en cola (envío) de App Engine y, luego, migra a Cloud Tasks

Pero todavía no llegamos ahí. Completa este codelab antes de considerar los próximos pasos. En la migración de este instructivo, se incluyen los siguientes pasos principales:

  1. Configurar/trabajo previo
  2. Agregar la biblioteca de Cloud NDB
  3. Actualizar archivos de la aplicación

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

Si completaste el codelab del módulo 1, te recomendamos volver a usar ese mismo proyecto (y el código). De manera alternativa, puedes crear un proyecto nuevo o reutilizar otro proyecto existente. Asegúrate de que el proyecto tenga una cuenta de facturación activa y que App Engine esté habilitado.

2. Obtén app de ejemplo del modelo de referencia

Uno de los requisitos es tener una app de ejemplo del módulo 1 que funcione. Usa tu solución si completaste ese instructivo. Puedes completarlo ahora (vínculo arriba), o si quieres omitirlo, copia el repositorio del módulo 1 (vínculo a continuación).

Sin importar si usas el tuyo o el nuestro, el código del módulo 1 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 “bonificación” opcional de Python 2 a 3):

La carpeta del código de INICIO del módulo 1 debe tener el siguiente contenido:

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

Si completaste el instructivo del módulo 1, también tendrás una carpeta lib con Flask y sus dependencias. Si no tienes una carpeta lib, ingrésela con el comando pip install -t lib -r requirements.txt para que podamos implementar esta aplicación de referencia en el siguiente paso. Si tienes instalado Python 2 y 3, se recomienda usar pip2 en lugar de pip para evitar confusiones con Python 3.

3. (Vuelve a ) implementar la app del Módulo 1

Los pasos del trabajo previo restantes para ejecutar ahora sin estos:

  1. Vuelve a familiarizarte con la herramienta de línea de comandos de gcloud (si es necesario).
  2. (Vuelve a )implementa el código del módulo 1 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.

Muchos servicios originales de App Engine se integran en sus propios productos, y Datastore es uno de ellos. En la actualidad, las aplicaciones que no son de App Engine pueden usar Cloud Datastore. Para los usuarios ndb de mucho tiempo, el equipo de Google Cloud creó la biblioteca cliente de Cloud NDB a fin de comunicarse con Cloud Datastore. Está disponible para Python 2 y 3.

Actualicemos los archivos de confirmación para reemplazar ndb de App Engine por Cloud NDB y, luego, modifiquemos nuestra aplicación.

1. Actualización requirements.txt

En el módulo 1, la única dependencia externa de nuestra app fue Flask. Ahora, agregaremos Cloud NDB. Así se verá tu archivo requirements.txt al final del módulo 1:

  • ANTES:
Flask==1.1.2

Para migrar desde App Engine ndb, necesitas la biblioteca de Cloud NDB (google-cloud-ndb), así que agrega su paquete a requirements.txt.

  • DESPUÉS:
Flask==1.1.2
google-cloud-ndb==1.7.1

Cuando se escribió este codelab, la última versión recomendada era 1.7.1, pero requirements.txt en el repositorio puede haber una versión más reciente. Recomendamos las últimas versiones de cada biblioteca, pero si no funcionan, puedes revertir a una versión anterior.

Borra la carpeta lib si tienes una y no la creaste antes. Ahora, vuelve a instalar las bibliotecas actualizadas con el comando pip install -t lib -r requirements.txt. Usa pip2 en lugar de pip según sea necesario.

2. Actualización app.yaml

Agregar bibliotecas cliente de Google Cloud como google-cloud-ndb tiene algunos requisitos, todo gira alrededor de la inclusión de Bibliotecas “integradas”, los paquetes de terceros ya están disponibles en los servidores de Google. No las enumeras en requirements.txt ni las copias con pip install. Estos son los únicos requisitos:

  1. Especificar bibliotecas integradas en app.yaml
  2. Apuntarlas a bibliotecas copiadas de terceros con las que pueden funcionar (en lib)

Esta es la app.yaml de INICIO del módulo 1:

  • ANTES:
runtime: python27
threadsafe: yes
api_version: 1

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

Ahora agrega las líneas siguientes a app.yaml para hacer referencia a un par de paquetes agrupados de terceros: grpcio y setuptools en una nueva sección de libraries:

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

¿Por qué usar estas bibliotecas integradas? gRPC es un framework de RPC abierto que usan todas las bibliotecas cliente de Google Cloud, incluida google-cloud-ndb. La biblioteca grpcio es el adaptador de gRPC de Python y, por lo tanto, es obligatorio. Pronto sabrás el motivo por el que se incluye setuptools.

  • DESPUÉS:

Con los cambios anteriores, el app.yaml actualizado debería verse así:

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

3. Actualización appengine_config.py

La herramienta pkg_resources, que forma parte de la biblioteca setuptools, se usa para permitir que las bibliotecas integradas de terceros accedan a las agrupadas. Actualiza appengine_config.py para usar pkg_resources a fin de dirigirlo a las bibliotecas empaquetadas en lib. Cuando hayas completado este cambio, el archivo completo se verá así:

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)

Con las formalidades del archivo de configuración al margen, ahora puedes migrar de ndb a Cloud NDB. Para completar la migración, actualiza las bibliotecas importadas y agrega el uso de la administración del contexto en main.py.

1. Importaciones

Realiza el siguiente cambio de importación en main.py:

  • ANTES
from google.appengine.ext import ndb
  • DESPUÉS:
from google.cloud import ndb

El cambio de una biblioteca de App Engine a una biblioteca de Google Cloud suele ser tan sutil como esta instancia. Para los servicios integrados que se convirtieron en productos de Google Cloud completos, importarás atributos de google.cloud, en lugar de google.appengine.

2. Acceso a Datastore

Para poder usar la biblioteca de Cloud NDB, tu aplicación debe usar administradores de contexto de Python. Su objetivo es “controlar” el acceso a los recursos para que puedan adquirirse antes de usarlos. Los administradores de contextos se basan en la técnica de control de informática que se conoce como La asignación de recursos es la inicialización (o RAII). Los administradores de contexto se usan con archivos de Python (que se deben abrir antes de poder acceder a ellos) y simultaneidad, los “bloqueos por subprocesos” deben adquirirse antes de que el código se pueda ejecutar en una “sección crítica”.

De manera similar, Cloud NDB requiere que adquieras el contexto de un cliente para comunicarte con Datastore antes de que se puedan ejecutar cualquier comando de Datastore. Primero, crea un cliente (ndb.Client()), agrega ds_client = ndb.Client() en main.py inmediatamente después de la inicialización de Flask:

app = Flask(__name__)
ds_client = ndb.Client()

El comando de Python with se usa solo para obtener el contexto de un objeto. Une los bloques del código que acceden a Datastore con declaraciones with.

A continuación, se muestran las mismas funciones del módulo 1 para escribir una entidad nueva en Datastore, y a fin de leer las entidades que recién se agregaron:

  • ANTES:

Este es el código original sin administración de contexto:

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 (v.to_dict() for v in Visit.query().order(
            -Visit.timestamp).fetch(limit))
  • DESPUÉS:

Ahora, agrega with ds_client.context(): y mueve el código de acceso de Datastore al bloque with:

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 (v.to_dict() for v in Visit.query().order(
                -Visit.timestamp).fetch(limit))

La aplicación principal de controlador sigue siendo idéntica a la del módulo 1, ya que no tenemos el código ndb (tampoco Cloud NDB):

@app.route('/')
def root():
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)
    return render_template('index.html', visits=visits)

Se recomienda garantizar una distinción clara entre el código de la aplicación y el acceso a los datos. De esta manera, el código principal de tu aplicación no cambia cuando se modifica el mecanismo de almacenamiento de datos subyacente como lo hicimos con esta migración.

Implemente la aplicación

Vuelve a implementar la app con gcloud app deploy y confirma que funciona. El código ahora debería coincidir con el contenido del Repositorio del módulo 2.

Si alcanzaste esta serie sin hacer ninguno de los Codelabs anteriores, la aplicación en sí no cambia. Registra todas las visitas a la página web principal (/) y tendrá esta apariencia una vez que hayas visitado el sitio muchas veces:

app de visitme

Felicitaciones por completar este codelab del módulo 2. Acabas de cruzar la línea de meta, ya que esta es la última de las migraciones muy recomendadas en esta serie, en lo que se refiere a 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

Desde aquí, hay una flexibilidad con respecto a tu próximo paso. Elige cualquiera de estas opciones:

  • Bonificación del módulo 2: Continúa a la parte adicional de este instructivo para explorar la transferencia a Python 3 y al entorno de ejecución de App Engine de última generación.
  • Módulo 7: Listas de tareas en cola de envío de App Engine (obligatorio si usas las listas de tareas en cola [enviar])
    • Agrega tareas de envío taskqueue de App Engine a la app del módulo 1
    • Prepara a los usuarios para la migración a Cloud Tasks en el módulo 8
  • Módulo 4: Migra a Cloud Run con Docker
    • Organiza tu aplicación en contenedores para que se ejecute en Cloud Run con Docker
    • Te permite quedarte 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 saber nada sobre Docker, contenedores ni Dockerfile.
    • Requiere que ya hayas migrado tu app a Python 3
  • Módulo 3:
    • Moderniza el acceso de Datastore de Cloud NDB a Cloud Datastore
    • Esta es la biblioteca que se usa para las aplicaciones de App Engine de Python 3 y las aplicaciones que no pertenecen a App Engine.

Para acceder a las funciones y el entorno de ejecución más recientes de App Engine, te recomendamos que migres a Python 3. En nuestra app de muestra, Datastore era el único servicio integrado que usábamos y, desde que migramos de ndb a Cloud NDB, podemos transferir el entorno de ejecución de Python 3 de App Engine.

Descripción general

Si bien la portabilidad a Python 3 no está dentro del alcance de un instructivo de Google Cloud, esta parte del codelab brinda a los desarrolladores una idea de cómo difiere el entorno de ejecución de Python 3 en App Engine. Una característica destacada del entorno de ejecución de última generación es el acceso simplificado a paquetes de terceros. No es necesario especificar paquetes integrados en app.yaml ni es un requisito para copiar o subir bibliotecas integradas. Se instalan de forma implícita a fin de que no aparezcan en requirements.txt.

Debido a que nuestra muestra es tan básica y Cloud NDB es compatible con Python 2 y 3, no se debe transferir ningún código de aplicación a 3.x de forma explícita. La app se ejecuta en 2.x y 3.x sin modificar, lo que significa que los únicos cambios necesarios se encuentran en la configuración en este caso:

  1. Simplifica app.yaml para hacer referencia a Python 3 y quita las bibliotecas de terceros.
  2. Borra appengine_config.py y la carpeta lib porque ya no son necesarias.

Además de main.py, los archivos requirements.txt y templates/index.html no se modifican.

Simplifica app.yaml

ANTES:

El único cambio real para esta app de muestra es acortar app.yaml de manera significativa. A modo de recordatorio, esto es lo que hicimos en app.yaml al final del módulo 2:

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

DESPUÉS:

En Python 3, las directivas threadsafe, api_version y libraries dejaron de estar disponibles. Se supone que todas las apps son seguras para los subprocesos y api_version no se usa en Python 3. Ya no hay paquetes de terceros integrados preinstalados en los servicios de App Engine, por lo que libraries también es obsoleto. Consulta la documentación sobre cambios en app.yaml para obtener más información sobre estos cambios. Como resultado, debes borrar los tres de app.yaml y actualizar a una versión de Python 3 compatible (consulta a continuación).

Uso de la directiva handlers

Además, la directiva handlers, que dirige el tráfico en las aplicaciones de App Engine, también dejó de estar disponible. Dado que el entorno de ejecución de última generación espera que los frameworks web administren el enrutamiento de las apps, todas las “secuencias de comandos del controlador” deben cambiarse a “auto”. Si combinas los cambios anteriores, llegarás a este app.yaml:

runtime: python38

handlers:
- url: /.*
  script: auto

Obtén más información sobre script: auto en su página de documentación.

Quita la directiva handlers

Como handlers dejó de estar disponible, también puedes quitar toda la sección y dejar una sola línea app.yaml:

runtime: python38

De forma predeterminada, esto iniciará el servidor web de Gunicorn WSGI, que está disponible para todas las aplicaciones. Si estás familiarizado con gunicorn, este es el comando que se ejecuta cuando se inicia de forma predeterminada con los barebones app.yaml:

gunicorn main:app --workers 2 -c /config/gunicorn.py

Opcional: Uso de la directiva entrypoint

Sin embargo, si tu aplicación requiere un comando de inicio específico, que se puede especificar con una directiva entrypoint en la que tu app.yaml se vería de la siguiente manera:

runtime: python38
entrypoint: python main.py

En este ejemplo, se solicita específicamente que se use el servidor de desarrollo de Flask en lugar de gunicorn. El código que inicia el servidor de desarrollo también se debe agregar a la app a fin de iniciar en la interfaz 0.0.0.0 en el puerto 8080. Para esto, agrega esta pequeña sección a la parte inferior de main.py:

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)

Obtén más información sobre entrypoint en la página de su documentación. Puedes encontrar más ejemplos y prácticas recomendadas en los documentos de inicio del entorno estándar de App Engine y en los documentos de inicio flexible de App Engine.

Borra appengine_config.py y lib

Borra el archivo appengine_config.py y la carpeta lib. Cuando migras a Python 3, App Engine adquiere y también instala paquetes enumerados en requirements.txt.

El archivo de configuración appengine_config.py se usa para reconocer las bibliotecas o los paquetes de terceros, sin importar si los copiaste o usas los que ya están disponibles en los servidores de App Engine (integrados). Cuando se migra a Python 3, un resumen de los grandes cambios es el siguiente:

  1. No hay un paquete de bibliotecas de terceros copiadas (se enumeran en requirements.txt)
  2. No hay pip install en una carpeta lib, lo que significa que no hay un período de carpeta lib
  3. No hay bibliotecas de terceros integradas en app.yaml
  4. No es necesario hacer referencia a la app a bibliotecas de terceros, por lo que no se necesita ningún archivo appengine_config.py

Todo lo que se necesita es enumerar las bibliotecas de terceros en requirements.txt.

Implemente la aplicación

Vuelve a implementar tu app para asegurarte de que funcione. También puedes confirmar qué tan cerca está tu solución del código de muestra de Python 3 del módulo 2. Para visualizar las diferencias con Python 2, compara el código con su versión de Python 2.

Felicitaciones por finalizar el paso adicional del módulo 2. Consulta la documentación sobre la preparación de archivos de configuración para el entorno de ejecución de Python 3. Por último, vuelve al paso anterior “Resumen/Limpieza” para conocer los próximos pasos y la limpieza.

Prepara tu aplicación

Cuando llegue el momento de migrar tu aplicación, deberás transferir tu main.py y otros archivos de la aplicación a 3.x, por lo que la práctica recomendada es tratar de hacer lo mejor para hacer que tu aplicación 2.x. sea compatible con versiones futuras con la mayor brevedad.

Hay muchos recursos en línea que te ayudarán a lograrlo, pero estos son algunos los consejos clave:

  1. Asegúrate de que todas las dependencias de las aplicaciones sean totalmente compatibles con 3.x
  2. Asegúrate de que la aplicación se ejecute al menos en 2.6 (preferentemente 2.7).
  3. Asegúrate de que la aplicación apruebe el conjunto de pruebas completo (y una cobertura mínima del 80%)
  4. Usa bibliotecas de compatibilidad como six, Future o Modernize.
  5. Infórmate sobre las diferencias clave de incompatibilidad con versiones anteriores (2.x) en comparación con las versiones 3.x
  6. Cualquier E/S tendrá como resultado una incompatibilidad con strings de Unicode en comparación con a la string de bytes

Como la app de muestra se diseñó teniendo en cuenta todo esto, entonces, por qué la app se ejecuta en 2.x y 3.x de inmediato para que podamos enfocarnos en mostrarte lo que se debe cambiar a fin de usar la plataforma de última generación.

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 1 (INICIAR) y el módulo 2 (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

Módulo 1

código

(n/a)

Módulo 2

código

código

Recursos de App Engine

A continuación, se muestran recursos adicionales con respecto a esta migración específica: