1. Descripción general
Esta serie de codelabs (instructivos de autoaprendizaje prácticos) tiene como objetivo ayudar a los desarrolladores de Google App Engine (estándar) a modernizar sus apps guiándolos a través de una serie de migraciones. La mayoría de esas migraciones implica dejar de lado los servicios agrupados en el entorno de ejecución original, ya que los entornos de ejecución de nueva generación son más flexibles y ofrecen a los usuarios una mayor variedad de opciones de servicio. Otra forma de modernizar una app incluye actualizarla a un producto más reciente, y ese es el tema de este codelab.
Los usuarios de App Engine que acceden a Datastore con las bibliotecas cliente de Cloud NDB o Cloud Datastore están listos y no necesitan realizar más migraciones. Sin embargo, Cloud Firestore representa el almacén de datos NoSQL más reciente, escalable y con alta disponibilidad con funciones de la base de datos en tiempo real de Firebase.
Estás en el lugar correcto si eres desarrollador y te sientes obligado a usar Firestore para aprovechar sus funciones o, al menos, si tienes suficiente interés en explorar lo que implica la migración. En este instructivo, aprenderás a migrar una app de App Engine con Cloud Datastore a Cloud Firestore.
Obtendrás información para hacer las siguientes acciones
- Reconocer las diferencias entre Datastore y Firestore
- Migra de Cloud Datastore a Cloud Firestore
Requisitos
- Un proyecto de Google Cloud Platform con lo siguiente:
- Habilidades básicas de Python
- Conocimiento práctico de los comandos comunes de Linux
- Conocimientos básicos sobre el desarrollo y la implementación de aplicaciones de App Engine
- Te recomendamos que completes el codelab del Módulo 3, incluida la portabilidad a Python 3, antes de comenzar este (módulo 6).
- Una aplicación en funcionamiento del Módulo 3 de Cloud Datastore para Python 3 de App Engine
Encuesta
¿Cómo usarás este codelab?
2. Información general
Datastore de App Engine se convirtió en su propio producto en 2013, Google Cloud Datastore, y ahora es accesible para los desarrolladores fuera de App Engine. Al año siguiente, Google adquirió Firebase. En ese momento, era conocida por su base de datos en tiempo real.
Durante los años siguientes, los equipos de Firebase y Cloud Datastore trabajaron en la integración de algunas de las funciones de Firebase en Datastore. Como resultado, en 2017, se lanzó la próxima generación de Cloud Datastore. Para reflejar la herencia de algunas funciones de Firebase, se cambió la marca a Cloud Firestore.
Cloud Firestore se convirtió en el mecanismo de almacenamiento NoSQL predeterminado para los proyectos de Google Cloud. Las apps nuevas pueden usar Cloud Firestore de forma nativa, mientras que las bases de datos de Datastore existentes se convirtieron a Firestore de forma interna y ahora funcionan como “Firestore en modo Datastore” para conservar la compatibilidad con las operaciones de Datastore. Como resultado, las aplicaciones solo pueden operar Cloud Firestore en uno de esos modos y, una vez configurado, no se pueden cambiar.
Actualmente, cuando los usuarios crean proyectos nuevos y seleccionan una solución NoSQL, se les solicita que seleccionen Firestore en modo Datastore o Firestore en modo nativo. Una vez que los usuarios agregan entidades de Datastore, no pueden cambiar a Firestore y, de manera similar, una vez que se selecciona el modo nativo de Firestore, ya no pueden volver a cambiar a Datastore (o a Firestore en modo Datastore). Para obtener más información, consulta la página sobre cómo elegir entre Cloud Firestore en modo Datastore o el modo nativo de Firestore en la documentación. Para migrar una app a Firestore, debes crear un proyecto nuevo, exportar Datastore y, luego, importarlo a Firestore. El propósito de este instructivo es darles a los desarrolladores una idea de las diferencias entre el uso de Cloud Datastore y Cloud Firestore.
No esperamos que realicen esta migración los usuarios, por lo que es opcional. Si bien el uso nativo de Cloud Firestore ofrece ventajas obvias, como la autenticación del cliente, la integración de reglas de Firebase y, por supuesto, la base de datos en tiempo real de Firebase, los pasos de migración son “inconvenientes”:
- Debes usar un proyecto diferente al proyecto de tu app actual.
- Un proyecto en el que una app agregó entidades de Datastore no se puede cambiar a Firestore en modo nativo
- De manera similar, un proyecto que seleccionó Firestore en modo nativo no puede volver a Firestore en modo Datastore.
- No existe una herramienta de migración que pueda transmitir datos de un proyecto a otro.
- Algunas funciones esenciales de Datastore, incluidos los espacios de nombres y una capacidad de procesamiento de escritura más alta (más de 10,000/s), no están disponibles en Firestore.
- Las herramientas de importación y exportación son "básicas" y "todo o nada" reales.
- Si tu app tiene muchas entidades de Datastore, puede demorar muchas horas exportar y, luego, importar a Firestore.
- Durante este tiempo, tu aplicación o servicio no podrá escribir ni actualizar datos.
- Las actividades de migración se tienen en cuenta para el uso normal. podría dividirlo (entre las cuotas diarias si es posible) para minimizar los costos.
- Debido a que tu nuevo servicio se ejecuta en un proyecto diferente, necesitarás una ventana para que se propaguen las actualizaciones de DNS.
- Datastore y Firestore tienen modelos de datos similares, pero diferentes, por lo que la migración requiere actualizar la forma en que funciona la aplicación o el servicio.
- Las consultas principales de Datastore ahora son consultas de recopilación de Firestore (opción predeterminada).
- Las consultas de tipo amplio de Datastore son consultas de grupos de colecciones de Firestore.
- Los índices y el manejo son diferentes, etcétera.
Dicho esto, si tienes una app bastante sencilla que considerar para la migración, si te preparas para simular una migración de este tipo o, simplemente, aquí para obtener más información sobre Datastore en comparación con Firestore, continúa.
Usuarios de Python 2: Este codelab de migración opcional se presenta solo en Python 3. Sin embargo, como Cloud Firestore también admite 2.x, los usuarios pueden interpolar las diferencias de uso. Un ejemplo es que los registros de Firestore usan strings Unicode (en lugar de strings de bytes), por lo que se requiere un indicador inicial u''
para los literales de string de Python 2, lo que significa que una función store_visit()
2.x se verá de la siguiente manera:
def store_visit(remote_addr, user_agent):
doc_ref = fs_client.collection(u'Visit')
doc_ref.add({
u'timestamp': datetime.now(),
u'visitor': u'{}: {}'.format(remote_addr, user_agent),
})
Aparte de eso, la biblioteca cliente debería funcionar de manera similar. El único otro problema que hay que tener en cuenta es que la biblioteca 2.x de Cloud Firestore está “congelada” en lo que respecta al desarrollo, por lo que cada vez más funciones nuevas (o nuevas) solo estarán disponibles en la biblioteca cliente de Firestore 3.x.
Cuando se continúa con esta migración, estos son los pasos principales de este instructivo:
- Configurar/trabajo previo
- Agrega la biblioteca de Cloud Firestore
- Actualizar archivos de 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
Te recomendamos que vuelvas a usar el mismo proyecto que usaste para completar el codelab del módulo 3. 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 previos de este codelab es tener una app de ejemplo del Módulo 3 que funcione. Si no tienes una, completa el instructivo del Módulo 3 (vínculo de arriba) antes de continuar con este paso. De lo contrario, si ya conoces su contenido, puedes comenzar por tomar el código del módulo 3 a continuación.
Sin importar si usas el tuyo o el nuestro, comenzaremos en el código del módulo 3. Este codelab del módulo 6 te guía a través de cada paso y, cuando se complete, debería parecerse al código en el punto de FINALIZAR. Este instructivo solo está disponible para Python 3.
- INICIO: Repositorio del módulo 3
- FIN: Repositorio del módulo 6
- Repositorio completo (clonar o descargar el archivo ZIP)
El directorio de los archivos del módulo 3 (tuyo o el nuestro) debería verse de la siguiente manera:
$ ls
README.md main.py templates
app.yaml requirements.txt
3. (Re)Implementa la app del Módulo 3
Los pasos del trabajo previo restantes para ejecutar ahora sin estos:
- Vuelve a familiarizarte con la herramienta de línea de comandos de
gcloud
(si es necesario). - Vuelve a implementar el código del módulo 3 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.
Requisitos de Python 2
- Asegúrate de que
app.yaml
(todavía) haga referencia a los paquetes de terceros:grpcio
ysetuptools
. - Asegúrate de que
appengine_config.py
aún usepkg_resources
ygoogle.appengine.ext.vendor
para apuntar la app a recursos de terceros. - En la siguiente sección, en la que se actualizará
requirements.txt
, deberás usargoogle-cloud-firestore==1.9.0
, ya que es la versión final compatible con 2.x de la biblioteca cliente de Firestore de Python.- Si tu
requirements.txt
tiene una entrada paragoogle-cloud-core
, déjala como está. - Borra
lib
y vuelve a instalarlo conpip install -t lib -r requirements.txt
.
- Si tu
4. Actualiza los archivos de configuración (agrega la biblioteca de Cloud Firestore)
Más allá de la configuración, los siguientes pasos necesarios son actualizar la configuración y, luego, los archivos de la aplicación. Para el primero, el único cambio de configuración es un intercambio de paquete menor en tu archivo requirements.txt
, así que hagámoslo ahora.
Reemplaza la línea google-cloud-datastore
por google-cloud-firestore
en requirements.txt
para que se vea de la siguiente manera:
Flask==1.1.2
google-cloud-firestore==2.0.2
Recomendamos usar las versiones más recientes de cada biblioteca. los números de versión anteriores son los más recientes al momento de este redacción. El código en la carpeta FINISH del repositorio se actualiza con mayor frecuencia y puede tener una versión más reciente.
No hay otros cambios de configuración, por lo que app.yaml
y templates/index.html
permanecen como están.
5. Actualizar archivos de la aplicación
Solo hay un archivo de aplicación, main.py
, por lo que todos los cambios de esta sección afectan solo a ese archivo.
1. Importaciones
Cambiar la importación del paquete implica un cambio menor de datastore
a firestore
:
- ANTES:
from google.cloud import datastore
- DESPUÉS:
from google.cloud import firestore
2. Acceso a Firestore
Después de inicializar Flask, crea tu cliente de Firestore. Realiza un cambio similar al anterior, pero para la inicialización del cliente:
- ANTES:
app = Flask(__name__)
ds_client = datastore.Client()
- DESPUÉS:
app = Flask(__name__)
fs_client = firestore.Client()
Cuando realizas la migración de Cloud NDB a Cloud Datastore, ya hiciste el trabajo pesado para llegar a Cloud Firestore. Con Datastore, puedes crear registros de datos en forma de entidades compuestas por propiedades comunes y agruparlos por claves. Los registros de datos de Firestore son documentos compuestos por pares clave-valor y se agrupan en colecciones. La migración desde Datastore requiere que pienses en estas diferencias, ya que se materializarán cuando crees registros de datos y los consultes. Los resultados pueden variar según la complejidad de tu código de Datastore.
En Datastore, se realizan consultas basadas en el tipo de entidad junto con los criterios de filtrado y orden. En Firestore, la consulta de datos es similar. Veamos un ejemplo rápido, suponiendo estos valores de consulta, clientes (ds_client
o fs_client
, respectivamente) e importaciones:
from datetime import datetime
from firestore.Query import DESCENDING
OCT1 = datetime(2020, 10, 1)
LIMIT = 10
Para Datastore, consultemos en orden descendente las diez entidades Visit
más recientes posteriores al 1 de octubre de 2020:
query = ds_client.query(kind='Visit')
query.add_filter('timestamp', '>=', datetime(2020, 10, 1))
query.order = ['-timestamp']
return query.fetch(limit=LIMIT)
Lo mismo para Firestore, de la colección Visit
:
query = fs_client.collection('Visit')
query.where('timestamp', '>=', datetime(2020, 10, 1))
query.order_by('timestamp', direction=DESCENDING)
return query.limit(LIMIT).stream()
La consulta de la app de ejemplo es más simple (sin cláusula "WHERE"). A modo de repaso, este es el código de Cloud Datastore:
- ANTES:
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)
Cuando migres a Firestore, encontrarás la creación de documentos nuevos similares a las entidades y las consultas, como se mostró antes.
- DESPUÉS:
def store_visit(remote_addr, user_agent):
doc_ref = fs_client.collection('Visit')
doc_ref.add({
'timestamp': datetime.now(),
'visitor': '{}: {}'.format(remote_addr, user_agent),
})
def fetch_visits(limit):
visits_ref = fs_client.collection('Visit')
visits = (v.to_dict() for v in visits_ref.order_by('timestamp',
direction=firestore.Query.DESCENDING).limit(limit).stream())
return visits
La función principal root()
se mantiene igual que el archivo de plantilla index.html
. Vuelve a comprobar los cambios, guárdalos, impleméntalos y verifícalos.
6. Resumen/limpieza
Implemente la aplicación
Vuelve a implementar la app con gcloud app deploy
y confirma que funciona. Ahora, tu código debería coincidir con el que se encuentra en el repositorio del módulo 6 (o una versión 2.x si lo prefieres).
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:
Felicitaciones por completar esta migración opcional del Módulo 6. Esta es probablemente una de las migraciones que puedes hacer, si no la final, en lo que respecta al almacenamiento de datos de App Engine. Otra migración alternativa que puedes considerar es la creación de contenedores para tu app para Cloud Run (si aún no lo has hecho, consulta los módulos 4 y 5, codelabs vinculados a continuación).
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. Mientras la app esté inhabilitada, no generará tráfico que genere cargos. Sin embargo, otro aspecto que se te puede facturar es el uso de Firestore si supera la cuota gratuita, por lo que debes borrar lo suficiente para no exceder ese límite.
Por otro lado, si no vas a continuar con las migraciones y quieres borrar todo por completo, puedes cerrar tu proyecto.
Próximos pasos
Más allá de este instructivo, hay otros codelabs de módulos de migración que puedes considerar:
- 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
- Agrega tareas de envío
- Módulo 4: Migra a Cloud Run con Docker
- Organiza tu aplicación en contenedores para que se ejecute en Cloud Run con Docker
- Esta migración te permite permanecer en Python 2.
- Módulo 5: Migra a Cloud Run con Cloud Buildpacks
- Crea contenedores para tu app a fin de que se ejecute en Cloud Run con paquetes de Cloud Build
- No necesitas conocer los detalles de Docker, contenedores, ni
Dockerfile
. - Requiere que tu app ya se haya migrado a Python 3 (Buildpacks no es compatible con Python 2).
7. 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, encontrarás los vínculos a las carpetas de repo del Módulo 3 (COMENZAR) y Módulo 6 (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 |
(código) | ||
Module 6 | (n/a) |
Recursos de App Engine
A continuación, se muestran recursos adicionales con respecto a esta migración específica:
- Referencias de Cloud Datastore y Cloud Firestore para Python
- Migra a Python 3 y GAE de entorno de ejecución de última generación
- General