Módulo 3: Migra de Google Cloud NDB a Cloud Datastore

1. Descripción general

Esta serie de codelabs (instructivos prácticos y de autoaprendizaje) tiene como objetivo ayudar a los desarrolladores de Google App Engine (entorno 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 opcional, se muestra a los desarrolladores cómo migrar de Cloud NDB a Cloud Datastore como la biblioteca cliente para comunicarse con el servicio de Datastore. Los desarrolladores que prefieran NDB pueden seguir usándolo, ya que es compatible con Python 3, por lo que esta migración es opcional. Esta migración solo es para quienes deseen compilar una base de código coherente y bibliotecas compartidas con otras apps que ya usan Cloud Datastore. Esto se explica en la sección "Antecedentes".

Obtendrás información para hacer las siguientes acciones

  • Usa Cloud NDB (si no estás familiarizado con él).
  • Migra de Cloud NDB a Cloud Datastore
  • Migra más tu app a Python 3

Requisitos

  • Un proyecto de Google Cloud Platform con una cuenta de facturación activa de GCP
  • Habilidades básicas de Python
  • Conocimiento práctico de comandos básicos de Linux
  • Conocimientos básicos sobre el desarrollo y la implementación de aplicaciones de App Engine
  • Una app de App Engine del módulo 2 2.x o 3.x en funcionamiento

Encuesta

¿Cómo usarás este codelab?

Solo lo leeré Lo leeré y completaré los ejercicios

2. Fondo

Si bien Cloud NDB es una excelente solución de Datastore para los desarrolladores de App Engine que usan la plataforma desde hace mucho tiempo y ayuda con la transición a Python 3, no es la única forma en que los desarrolladores de App Engine pueden acceder a Datastore. Cuando Datastore de App Engine se convirtió en su propio producto en 2013, se creó una nueva biblioteca cliente de Cloud Datastore de Google para que todos los usuarios pudieran usar Datastore.

Se recomienda a los desarrolladores de App Engine y no App Engine de Python 3 que usen Cloud Datastore (no Cloud NDB). Se recomienda a los desarrolladores de App Engine de Python 2 que migren de ndb a Cloud NDB y, desde allí, a Python 3, pero también pueden optar por migrar a Cloud Datastore. Esta es una decisión lógica, en especial para los desarrolladores que ya tienen código que usa Cloud Datastore, como los que se mencionaron anteriormente, y desean crear bibliotecas compartidas en todas sus aplicaciones. La reutilización y la coherencia del código son prácticas recomendadas que contribuyen a reducir el costo general de mantenimiento, como se resume aquí:

Migración de Cloud NDB a Cloud Datastore

  • Permite que los desarrolladores se enfoquen en una sola base de código para el acceso a Datastore
  • Evita mantener parte del código con Cloud NDB y otra parte con Cloud Datastore
  • Proporciona más coherencia en la base de código y una mejor reutilización del código
  • Permite el uso de bibliotecas comunes o compartidas, lo que contribuye a reducir el costo general de mantenimiento

Esta migración incluye los siguientes pasos principales:

  1. Configurar/trabajo previo
  2. Reemplaza Cloud NDB por las bibliotecas cliente de Cloud Datastore
  3. Actualiza la aplicación

3. Configurar/trabajo previo

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 2, 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 (app) 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 2 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 2 (vínculo a continuación).

Sin importar si usas el tuyo o el nuestro, el código del módulo 2 es el que tendremos en cuenta. Este codelab del módulo 3 te guiará en cada paso y, cuando se complete, debería parecerse al código en el punto FINALIZAR. Existen versiones de Python 2 y 3 de este instructivo, así que obtén el repo de código correcto a continuación.

Python 2

El directorio de archivos de INICIO del módulo 2 de Python 2 (los tuyos o los nuestros) debe ser similar al siguiente:

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

Si completaste el instructivo del módulo 2, 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.

Python 3

El directorio de archivos de INICIO del módulo 2 de Python 3 (los tuyos o los nuestros) debe ser similar al siguiente:

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

No se usan ni lib ni appengine_config.py para Python 3.

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

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.

4. Reemplaza Cloud NDB por las bibliotecas cliente de Cloud Datastore

El único cambio de configuración es un pequeño intercambio de paquetes en tu archivo requirements.txt.

1. Actualizar requirements.txt

Cuando completaste el módulo 2, tu archivo requirements.txt se veía de la siguiente manera:

  • ANTES (Python 2 y 3):
Flask==1.1.2
google-cloud-ndb==1.7.1

Actualiza requirements.txt reemplazando la biblioteca de Cloud NDB (google-cloud-ndb) por la versión más reciente de la biblioteca de Cloud Datastore (google-cloud-datastore), dejando intacta la entrada de Flask, teniendo en cuenta que la versión final de Cloud Datastore que es compatible con Python 2 es la 1.15.3:

  • DESPUÉS (Python 2):
Flask==1.1.2
google-cloud-datastore==1.15.3
  • DESPUÉS (Python 3):
Flask==1.1.2
google-cloud-datastore==2.1.0

Ten en cuenta que el repositorio se mantiene con más frecuencia que este instructivo, por lo que es posible que el archivo requirements.txt refleje versiones más recientes. Recomendamos usar las versiones más recientes de cada biblioteca, pero si no funcionan, puedes revertir a una versión anterior. Los números de versión anteriores son los más recientes cuando se actualizó este codelab por última vez.

2. Otros archivos de configuración

Los otros archivos de configuración, app.yaml y appengine_config.py, deben permanecer sin cambios desde el paso de migración anterior:

  • app.yaml debe (aún) hacer referencia a los paquetes agrupados de terceros grpcio y setuptools.
  • appengine_config.py aún debe apuntar pkg_resources y google.appengine.ext.vendor a los recursos de terceros en lib.

Ahora, pasemos a los archivos de la aplicación.

5. Actualizar archivos de la aplicación

No hay cambios en template/index.html, pero sí algunas actualizaciones para main.py.

1. Importaciones

El código de inicio de la sección de importación debería verse de la siguiente manera:

  • ANTES:
from flask import Flask, render_template, request
from google.cloud import ndb

Reemplaza la importación google.cloud.ndb por una para Cloud Datastore: google.cloud.datastore. Dado que la biblioteca cliente de Datastore no admite la creación automática de un campo de marca de tiempo en una entidad, también debes importar el módulo datetime de la biblioteca estándar para crear uno de forma manual. Por convención, las importaciones de bibliotecas estándar se colocan antes de las importaciones de paquetes de terceros. Cuando termines de aplicar estos cambios, debería verse así:

  • DESPUÉS:
from datetime import datetime
from flask import Flask, render_template, request
from google.cloud import datastore

2. Inicialización y modelo de datos

Después de inicializar Flask, la app de ejemplo del Módulo 2 que crea una clase de modelo de datos de NDB y sus campos se ve de la siguiente manera:

  • ANTES:
app = Flask(__name__)
ds_client = ndb.Client()

class Visit(ndb.Model):
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)

La biblioteca de Cloud Datastore no tiene esa clase, por lo que debes borrar la declaración de la clase Visit. Aún necesitas un cliente para comunicarte con Datastore, así que cambia ndb.Client() por datastore.Client(). La biblioteca de Datastore es más "flexible", ya que te permite crear entidades sin "declarar previamente" su estructura como NDB. Después de esta actualización, esta parte de main.py debería verse de la siguiente manera:

  • DESPUÉS:
app = Flask(__name__)
ds_client = datastore.Client()

3. Acceso a Datastore

La migración a Cloud Datastore requiere que cambies la forma en que creas, almacenas y consultas entidades de Datastore (a nivel del usuario). En el caso de tus aplicaciones, la dificultad de esta migración depende de la complejidad del código de Datastore. En nuestra app de ejemplo, intentamos que la actualización fuera lo más sencilla posible. Este es nuestro código inicial:

  • ANTES:
def store_visit(remote_addr, user_agent):
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

def fetch_visits(limit):
    with ds_client.context():
        return (v.to_dict() for v in Visit.query().order(
                -Visit.timestamp).fetch_page(limit)[0])

Con Cloud Datastore, crea una entidad genérica que identifique los objetos agrupados en tu entidad con una "clave". Crea el registro de datos con un objeto JSON (dict de Python) de pares clave-valor y, luego, escríbelo en Datastore con el put() esperado. Las consultas son similares, pero más sencillas con Datastore. Aquí puedes ver cómo difiere el código equivalente de Datastore:

  • DESPUÉS:
def store_visit(remote_addr, user_agent):
    entity = datastore.Entity(key=ds_client.key('Visit'))
    entity.update({
        'timestamp': datetime.now(),
        'visitor': '{}: {}'.format(remote_addr, user_agent),
    })
    ds_client.put(entity)

def fetch_visits(limit):
    query = ds_client.query(kind='Visit')
    query.order = ['-timestamp']
    return query.fetch(limit=limit)

Actualiza los cuerpos de las funciones para store_visit() y fetch_visits() como se indicó anteriormente, y mantén sus firmas idénticas a las de la versión anterior. No hay ningún cambio en el controlador principal root(). Después de completar estos cambios, tu app estará equipada para usar Cloud Datastore y lista para la prueba.

6. Resumen/Limpieza

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 de las carpetas del repositorio del módulo 3:

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 3. Ahora sabes que puedes usar las bibliotecas cliente de Cloud NDB y Cloud Datastore para acceder a Datastore. Si migras a esta última, ahora puedes obtener los beneficios de las bibliotecas compartidas, el código común y la reutilización del código para lograr coherencia y reducir el costo de mantenimiento.

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í, puedes explorar los siguientes módulos de migración:

  • Bonificación del módulo 3: Continúa a la sección de bonificación para aprender a transferir 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 conocer los detalles de Docker, contenedores, ni Dockerfile.
    • Requiere que ya hayas migrado tu app a Python 3
  • Módulo 6: Migra a Cloud Firestore
    • Migra a Cloud Firestore para acceder a las funciones de Firebase
    • Si bien Cloud Firestore es compatible con Python 2, este codelab solo está disponible en Python 3.

7. BONIFICACIÓN: migra a Python 3

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 Datastore 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 la referencia a las bibliotecas de terceros incluidas.
  2. Borra appengine_config.py y la carpeta lib porque ya no son necesarias.

Los archivos de aplicación main.py y templates/index.html no se modifican.

Actualizar requirements.txt

La versión final de Cloud Datastore que admite Python 2 es la 1.15.3. Actualiza requirements.txt con la versión más reciente de Python 3 (es posible que ya sea más reciente). Cuando se escribió este instructivo, la versión más reciente era la 2.1.0, por lo que debes editar esa línea para que se vea así (o como sea la versión más reciente):

google-cloud-datastore==2.1.0

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 3:

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

Opcional: 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 la página de referencia de app.yaml.

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, se puede especificar con una directiva entrypoint, lo que generará un app.yaml que se verá 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. También se debe agregar a tu app el código que inicia el servidor de desarrollo para que se inicie en la interfaz 0.0.0.0 en el puerto 8080. Para ello, agrega esta pequeña sección en 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 referencia de app.yaml. 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 del entorno 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 e instala los paquetes que se enumeran 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 se agrupan las bibliotecas copiadas de terceros (que se indican 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 se enumeran las 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 3. 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 3. Consulta la documentación sobre la preparación de archivos de configuración para el entorno de ejecución de Python 3. Por último, revisa el resumen anterior para conocer los próximos pasos y la limpieza.

Prepara tu solicitud

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.

8. Recursos adicionales

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

En la siguiente tabla, puedes encontrar vínculos a las carpetas del repositorio para el módulo 2 (INICIAR) y el módulo 3 (FINALIZAR). También se puede acceder a ellos desde el repositorio de todas las migraciones de App Engine, que puedes clonar o descargar un archivo ZIP.

Codelab

Python 2

Python 3

Módulo 2

código

código

Module 3

código

código

Recursos de App Engine

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