Migra de App Engine Blobstore a Cloud Storage (módulo 16)

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.

En este codelab, aprenderás a migrar desde Blobstore de App Engine a Cloud Storage. También hay migraciones implícitas desde:

Consulta los módulos de migración relacionados para obtener más información paso a paso.

En un próximo lab,

  • Agrega el uso de la API o la biblioteca de Blobstore de App Engine
  • Almacena las cargas de los usuarios al servicio de Blobstore
  • Prepárate para el próximo paso de la migración a Cloud Storage

Requisitos

Encuesta

¿Cómo usarás este instructivo?

Leer Leer y completar 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

Este codelab comienza con la app de ejemplo del módulo 15 y demuestra cómo migrar de Blobstore (y NDB) a Cloud Storage (y Cloud NDB). El proceso de migración implica reemplazar las dependencias de los paquetes de servicios heredados de App Engine, que te permiten mover tus apps a otra plataforma sin servidores en la nube o a otra plataforma de hosting, si así lo deseas.

Esta migración requiere un poco más de esfuerzo en comparación con las otras migraciones de esta serie. Blobstore tiene dependencias en el marco de trabajo de aplicaciones web original y es el motivo por el que la aplicación de muestra usa el marco de trabajo webapp2 en lugar de Flask. En este instructivo, se presentan migraciones a Cloud Storage, Cloud NDB, Flask y Python 3.

La app sigue registrando las "visitas" del usuario final y muestra los diez más recientes, pero el codelab anterior (Módulo 15) agregó una nueva funcionalidad para adaptarse al uso de Blobstore: la app solicita a los usuarios finales que suban un artefacto (un archivo) correspondiente a su “visita”. Los usuarios pueden hacerlo o seleccionar "omitir" para inhabilitarla. Independientemente de la decisión del usuario, la página siguiente procesa el mismo resultado que las versiones anteriores de esta app y muestra las visitas más recientes. Un giro adicional es que las visitas con los artefactos correspondientes incluyen una "vista". para mostrar el artefacto de una visita. En este codelab, se implementan las migraciones mencionadas anteriormente y se conserva la funcionalidad descrita.

3. Configurar/trabajo previo

Antes de llegar a la parte principal del instructivo, configuremos el proyecto, obtengamos el código y, luego, implementemos la app de referencia para que sepamos que comenzamos a trabajar con el código.

1. Configura el proyecto

Si ya implementaste la app del módulo 15, te recomendamos que vuelvas a usar ese mismo proyecto (y código). Como alternativa, puedes crear un proyecto completamente nuevo o reutilizar otro proyecto existente. Asegúrate de que el proyecto tenga una cuenta de facturación activa y App Engine 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 15 que funcione. Si no la tienes, puedes obtenerla en el Módulo 15, "COMENZAR" (vínculo más abajo). En este codelab, se explica cada paso y se concluye con un código similar al que se muestra en el módulo 16, "FINALIZAR" carpeta.

El directorio de los archivos STARTing del módulo 15 debería verse de la siguiente manera:

$ ls
README.md       app.yaml        main-gcs.py     main.py         templates

El archivo main-gcs.py es una versión alternativa de main.py del módulo 15 que permite seleccionar un bucket de Cloud Storage diferente del predeterminado de la URL asignada a una app según el ID del proyecto: PROJECT_ID.appspot.com. Este archivo no participa en este codelab (Módulo 16). Solo se pueden aplicar técnicas de migración similares a ese archivo si lo deseas.

3. (vuelve a) implementa la aplicación de modelo de referencia

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

  1. Familiarízate con la herramienta de línea de comandos de gcloud
  2. Vuelve a implementar la app de muestra con gcloud app deploy
  3. Confirma que la app se ejecuta en App Engine sin problemas

Una vez que hayas ejecutado correctamente esos pasos y confirmes que la app del Módulo 15 funciona. La página inicial recibe a los usuarios con un formulario que les solicita que suba un archivo de artefacto de visitas junto con una opción: "omitir" para inhabilitarlo:

f5b5f9f19d8ae978.png

Una vez que los usuarios suben un archivo o lo omiten, la app renderiza las "visitas más recientes" que ya conocen. página:

f5ac6b98ee8a34cb.png

Las visitas que incluyan un artefacto tendrán una "vista" a la derecha de la marca de tiempo de la visita para mostrar (o descargar) el artefacto. Una vez que confirmes la funcionalidad de la app, estará todo listo para migrar de los servicios heredados de App Engine (webapp2, NBS, Blobstore) a alternativas contemporáneas (Flask, Cloud NDB y Cloud Storage).

4. Actualiza archivos de configuración

Tres archivos de configuración entran en juego para la versión actualizada de nuestra app. Las tareas requeridas son las siguientes:

  1. Actualiza las bibliotecas de terceros integradas necesarias en app.yaml y deja la puerta abierta para una migración a Python 3.
  2. Agrega un requirements.txt, que especifica todas las bibliotecas necesarias que no están integradas.
  3. Se agregó appengine_config.py para que la app admita bibliotecas de terceros integradas y no integradas.

app.yaml

Actualiza la sección libraries para editar tu archivo app.yaml. Se quitó jinja2 y se agregaron grpcio, setuptools y ssl. Elige la versión más reciente disponible para las tres bibliotecas. También agrega la directiva runtime de Python 3, pero se marcó como comentario. Cuando termines, debería verse de la siguiente manera (si seleccionaste Python 3.9):

ANTES:

runtime: python27
threadsafe: yes
api_version: 1

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

libraries:
- name: jinja2
  version: latest

DESPUÉS:

#runtime: python39
runtime: python27
threadsafe: yes
api_version: 1

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

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

Los cambios se relacionan principalmente con las bibliotecas integradas de Python 2 disponibles en los servidores de App Engine (por lo que no tienes que agruparlas por tu cuenta). Quitamos Jinja2 porque viene con Flask, que agregaremos a reqs.txt. Cada vez que se usan las bibliotecas cliente de Google Cloud, como las de Cloud NDB y Cloud Storage, se necesitan grpcio y setuptools. Por último, Cloud Storage requiere la biblioteca SSL. La directiva de entorno de ejecución comentada que aparece en la parte superior sirve para cuando tengas todo listo para transferir esta app a Python 3. Abordaremos este tema al final de este instructivo.

requirements.txt

Agrega un archivo requirements.txt, que requiere el framework de Flask y las bibliotecas cliente de Cloud NDB y Cloud Storage, ninguna de las cuales está integrada. Crea el archivo con este contenido:

flask
google-cloud-ndb
google-cloud-storage

El entorno de ejecución de App Engine para Python 2 requiere la agrupación automática de bibliotecas de terceros no integradas. Por lo tanto, ejecuta el siguiente comando para instalar estas bibliotecas en la carpeta lib:

pip install -t lib -r requirements.txt

Si tienes Python 2 y 3 en tu máquina de desarrollo, es posible que debas usar el comando de pip2 para asegurarte de obtener las versiones Python 2 de estas bibliotecas. Una vez que actualices a Python 3, ya no necesitarás empaquetar tú mismo.

appengine_config.py

Agrega un archivo appengine_config.py que admita bibliotecas de terceros integradas y no integradas. Crea el archivo con este contenido:

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)

Los pasos que acabas de completar deben ser similares o idénticos a los que se indican en la sección Instala bibliotecas para apps de Python 2 de los documentos de App Engine y, más específicamente, el contenido de appengine_config.py debe coincidir con el que aparece en el Paso 5.

Ya se completó el trabajo en los archivos de configuración, así que pasemos a la aplicación.

5. Modifica archivos de la aplicación

Importaciones

El primer conjunto de cambios para main.py incluye el intercambio de todos los elementos que se reemplazarán. Esto es lo que cambiará:

  1. Se reemplazó webapp2 por Flask.
  2. En lugar de usar Jinja2 de webapp2_extras, usa el Jinja2 que viene con Flask.
  3. Cloud NDB y Cloud Storage reemplazaron App Engine Blobstore y NDB
  4. Los controladores de Blobstore en webapp se reemplazaron por una combinación de las utilidades del módulo de biblioteca estándar io, Flask y werkzeug
  5. De forma predeterminada, Blobstore escribe en un bucket de Cloud Storage con el nombre de la URL de tu app (PROJECT_ID.appspot.com). Debido a que estamos realizando la portabilidad a la biblioteca cliente de Cloud Storage, se usa google.auth para obtener el ID del proyecto y especificar exactamente el mismo nombre de bucket. Puedes cambiar el nombre del bucket, ya que ya no está codificado.

ANTES:

import webapp2
from webapp2_extras import jinja2
from google.appengine.ext import blobstore, ndb
from google.appengine.ext.webapp import blobstore_handlers

Para implementar los cambios de la lista anterior, reemplaza la sección de importación actual en main.py con el siguiente fragmento de código.

DESPUÉS:

import io

from flask import (Flask, abort, redirect, render_template,
        request, send_file, url_for)
from werkzeug.utils import secure_filename

import google.auth
from google.cloud import exceptions, ndb, storage

Inicialización y compatibilidad innecesaria con Jinja2

El siguiente bloque de código que se debe reemplazar es el BaseHandler que especifica el uso de Jinja2 de webapp2_extras. Esto no es necesario porque Jinja2 viene con Flask y es su motor de plantillas predeterminado, así que quítelo.

En el módulo 16, crea instancias de objetos que no teníamos en la app anterior. Esto incluye inicializar la app de Flask y crear clientes de la API para Cloud NDB y Cloud Storage. Por último, armamos el nombre del bucket de Cloud Storage como se describió anteriormente en la sección de importaciones. Estas son las situaciones previas y posteriores a la implementación de estas actualizaciones:

ANTES:

class BaseHandler(webapp2.RequestHandler):
    'Derived request handler mixing-in Jinja2 support'
    @webapp2.cached_property
    def jinja2(self):
        return jinja2.get_jinja2(app=self.app)

    def render_response(self, _template, **context):
        self.response.write(self.jinja2.render_template(_template, **context))

DESPUÉS:

app = Flask(__name__)
ds_client = ndb.Client()
gcs_client = storage.Client()
_, PROJECT_ID = google.auth.default()
BUCKET = '%s.appspot.com' % PROJECT_ID

Actualiza el acceso a Datastore

Cloud NDB es mayormente compatible con App Engine NDB. Una diferencia que ya se aborda es la necesidad de un cliente de API. Otro es el último requiere que el administrador de contexto de Python del cliente de la API controle el acceso a Datastore. En esencia, esto significa que todas las llamadas de acceso a Datastore con la biblioteca cliente de Cloud NDB solo pueden ocurrir dentro de los bloques with de Python.

Es un cambio. y la otra es que Blobstore y sus objetos, p.ej., Los objetos BlobKey no son compatibles con Cloud Storage, por lo que debes cambiar file_blob para que sea ndb.StringProperty en su lugar. A continuación, se muestran la clase de modelo de datos y las funciones store_visit() y fetch_visits() actualizadas que reflejan estos cambios:

ANTES:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)
    file_blob = ndb.BlobKeyProperty()

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    Visit(visitor='{}: {}'.format(remote_addr, user_agent),
            file_blob=upload_key).put()

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

DESPUÉS:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)
    file_blob = ndb.StringProperty()

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent),
                file_blob=upload_key).put()

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

Esta es una representación ilustrativa de los cambios que se realizaron hasta el momento:

a8f74ca392275822.png

Actualiza los controladores

Subir controlador

Los controladores en webapp2 son clases mientras son funciones en Flask. En lugar de un método de verbo HTTP, Flask usa el verbo para decorar la función. Blobstore y sus controladores webapp se reemplazaron por la funcionalidad de Cloud Storage, así como de Flask y sus utilidades:

ANTES:

class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
    'Upload blob (POST) handler'
    def post(self):
        uploads = self.get_uploads()
        blob_id = uploads[0].key() if uploads else None
        store_visit(self.request.remote_addr, self.request.user_agent, blob_id)
        self.redirect('/', code=307)

DESPUÉS:

@app.route('/upload', methods=['POST'])
def upload():
    'Upload blob (POST) handler'
    fname = None
    upload = request.files.get('file', None)
    if upload:
        fname = secure_filename(upload.filename)
        blob = gcs_client.bucket(BUCKET).blob(fname)
        blob.upload_from_file(upload, content_type=upload.content_type)
    store_visit(request.remote_addr, request.user_agent, fname)
    return redirect(url_for('root'), code=307)

Notas sobre esta actualización:

  • En lugar de blob_id, los artefactos de archivo ahora se identifican por nombre de archivo (fname) si está presente y None en caso contrario (el usuario inhabilitó la carga de un archivo).
  • Los controladores de Blobstore abstraen el proceso de carga de sus usuarios, pero Cloud Storage no lo hace, de modo que puedes ver el código recién agregado que establece el objeto BLOB y la ubicación (bucket) del archivo, así como la llamada que realiza la carga real. (upload_from_file()).
  • webapp2 usa una tabla de enrutamiento en la parte inferior del archivo de la aplicación, mientras que las rutas de Flask se encuentran en cada controlador decorado.
  • Para completar su funcionalidad, ambos controladores redireccionan a la página principal ( /) y conservan la solicitud POST con un código de retorno HTTP 307.

Descargar controlador

La actualización del controlador de descarga sigue un patrón similar al de carga, solo que hay mucho menos código que analizar. Reemplaza la funcionalidad de Blobstore y webapp por los equivalentes de Cloud Storage y Flask:

ANTES:

class ViewBlobHandler(blobstore_handlers.BlobstoreDownloadHandler):
    'view uploaded blob (GET) handler'
    def get(self, blob_key):
        self.send_blob(blob_key) if blobstore.get(blob_key) else self.error(404)

DESPUÉS:

@app.route('/view/<path:fname>')
def view(fname):
    'view uploaded blob (GET) handler'
    blob = gcs_client.bucket(BUCKET).blob(fname)
    try:
        media = blob.download_as_bytes()
    except exceptions.NotFound:
        abort(404)
    return send_file(io.BytesIO(media), mimetype=blob.content_type)

Notas sobre esta actualización:

  • Nuevamente, Flask decora las funciones de controlador con su ruta, mientras que webapp lo hace en una tabla de enrutamiento en la parte inferior, por lo que debes reconocer la sintaxis de coincidencia de patrones de este último, ('/view/([^/]+)?') en comparación con la de Flask ('/view/<path:fname>').
  • Al igual que con el controlador de carga, se requiere un poco más de trabajo en Cloud Storage para la funcionalidad abstracta de los controladores de Blobstore, es decir, identificar el archivo (BLOB) en cuestión y descargar explícitamente el objeto binario en comparación con la única llamada al método send_blob() del controlador de Blobstore.
  • En ambos casos, se muestra un error HTTP 404 al usuario si no se encuentra un artefacto.

Controlador principal

Los cambios finales en la aplicación principal se realizan en el controlador principal. Los métodos del verbo HTTP webapp2 se reemplazan por una sola función que combina su funcionalidad. Reemplaza la clase MainHandler por la función root() y quita la tabla de enrutamiento webapp2 como se muestra a continuación:

ANTES:

class MainHandler(BaseHandler):
    'main application (GET/POST) handler'
    def get(self):
        self.render_response('index.html',
                upload_url=blobstore.create_upload_url('/upload'))

    def post(self):
        visits = fetch_visits(10)
        self.render_response('index.html', visits=visits)

app = webapp2.WSGIApplication([
    ('/', MainHandler),
    ('/upload', UploadHandler),
    ('/view/([^/]+)?', ViewBlobHandler),
], debug=True)

DESPUÉS:

@app.route('/', methods=['GET', 'POST'])
def root():
    'main application (GET/POST) handler'
    context = {}
    if request.method == 'GET':
        context['upload_url'] = url_for('upload')
    else:
        context['visits'] = fetch_visits(10)
    return render_template('index.html', **context)

En lugar de separar los métodos get() y post(), son, en esencia, una sentencia if-else en root(). Además, debido a que root() es una única función, solo hay una llamada con el objetivo de renderizar la plantilla tanto para GET como para POST, pero no es posible en webapp2.

A continuación, se incluye una representación visual del segundo y último conjunto de cambios de main.py:

5ec38818c32fec2.png

"Mejora" de la retrocompatibilidad (opcional)

Entonces, la solución creada anteriormente funciona a la perfección, pero solo si comienzas desde cero y no tienes archivos creados por Blobstore. Debido a que actualizamos la app para identificar archivos por nombre de archivo en lugar de BlobKey, la app del Módulo 16 completada sin modificaciones no podrá ver los archivos de Blobstore. En otras palabras, realizamos un cambio incompatible con las versiones anteriores cuando realizamos esta migración. Ahora presentamos una versión alternativa de main.py llamada main-migrate.py (que se encuentra en el repositorio) que intenta reducir esta brecha.

La primera "extensión" Para admitir archivos creados en Blobstore, hay un modelo de datos que tiene un BlobKeyProperty (además de un StringProperty para los archivos creados en Cloud Storage):

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)
    file_blob = ndb.BlobKeyProperty()  # backwards-compatibility
    file_gcs  = ndb.StringProperty()

La propiedad file_blob se usará para identificar los archivos creados en Blobstore, mientras que file_gcs es para archivos de Cloud Storage. Ahora, cuando crees visitas nuevas, almacena explícitamente un valor en file_gcs en lugar de file_blob, de modo que store_visit se ve un poco diferente:

ANTES:

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent),
                file_blob=upload_key).put()

DESPUÉS:

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent),
                file_gcs=upload_key).put()

Cuando recupere las visitas más recientes, "normalice" los datos antes de enviarlos a la plantilla:

ANTES:

@app.route('/', methods=['GET', 'POST'])
def root():
    'main application (GET/POST) handler'
    context = {}
    if request.method == 'GET':
        context['upload_url'] = url_for('upload')
    else:
        context['visits'] = fetch_visits(10)
    return render_template('index.html', **context)

DESPUÉS:

@app.route('/', methods=['GET', 'POST'])
def root():
    'main application (GET/POST) handler'
    context = {}
    if request.method == 'GET':
        context['upload_url'] = url_for('upload')
    else:
        context['visits'] = etl_visits(fetch_visits(10))
    return render_template('index.html', **context)

A continuación, confirma la existencia de file_blob o file_gcs (o ninguno). Si hay un archivo disponible, elige el que exista y usa ese identificador (BlobKey para archivos creados en Blobstore o nombre de archivo para archivos creados en Cloud Storage). Cuando decimos “Archivos creados en Cloud Storage”, nos referimos a archivos que se crean con la biblioteca cliente de Cloud Storage. Blobstore también escribe en Cloud Storage, pero, en este caso, esos serían archivos creados por Blobstore.

Ahora más importante, ¿cuál es la función etl_visits() que se usa para normalizar o ETL (extraer, transformar y cargar) los datos para el usuario final? El aspecto resultante será el siguiente:

def etl_visits(visits):
    return [{
            'visitor': v.visitor,
            'timestamp': v.timestamp,
            'file_blob': v.file_gcs if hasattr(v, 'file_gcs') \
                    and v.file_gcs else v.file_blob
            } for v in visits]

Probablemente se ve como lo que esperabas: el código repite todas las visitas y, para cada visita, toma los datos del visitante y de la marca de tiempo de forma literal. Luego, comprueba si existen file_gcs o file_blob y, de ser así, selecciona una de ellas (o None si no existe ninguna).

A continuación, se muestra una ilustración de las diferencias entre main.py y main-migrate.py:

718b05b2adadb2e1.png

Si comienzas desde cero sin archivos creados por Blobstore, usa main.py, pero si quieres realizar una transición y deseas archivos complementarios creados por Blobstore y Cloud Storage, consulta main-migrate.py como ejemplo de cómo abordar situaciones como para ayudarte a planificar migraciones para tus propias apps. Cuando se realizan migraciones complejas, es probable que surjan casos especiales, por lo que este ejemplo pretende mostrar una mayor afinidad por la modernización de apps reales con datos reales.

6. 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 los pasos de limpieza y considera los siguientes.

Implementa y verifica la aplicación

Antes de volver a implementar tu app, asegúrate de ejecutar pip install -t lib -r requirements.txt para obtener esas bibliotecas de terceros empaquetadas automáticamente en la carpeta lib. Si deseas ejecutar la solución retrocompatible, primero cambia el nombre de main-migrate.py a main.py. Ahora, ejecuta gcloud app deploy y confirma que la app funcione de manera idéntica a la del Módulo 15. La pantalla del formulario se ve de la siguiente manera:

f5b5f9f19d8ae978.png

La página de visitas más recientes se ve así:

f5ac6b98ee8a34cb.png

Felicitaciones por completar este codelab para reemplazar App Engine Blobstore por Cloud Storage, App Engine NDB por Cloud NDB y webapp2 por Flask. Tu código ahora debería coincidir con el que está en la carpeta FINISH (Módulo 16). El main-migrate.py alternativo también está presente en esa carpeta.

“Migración” de Python 3

La directiva runtime de Python 3 comentada en la parte superior de app.yaml es todo lo que se necesita para transferir esta app a Python 3. El código fuente en sí ya es compatible con Python 3, de modo que no se necesitan cambios allí. Para implementar esto como una aplicación de Python 3, ejecuta los siguientes pasos:

  1. Quita el comentario de la directiva runtime de Python 3 en la parte superior de app.yaml.
  2. Borra todas las demás líneas de app.yaml.
  3. Borra el archivo appengine_config.py. (no se usa en el entorno de ejecución de Python 3)
  4. Borra la carpeta lib si existe. (no es necesario con el entorno de ejecución de 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:

Ten en cuenta que, si migraste del módulo 15 al 16, seguirás teniendo datos en Blobstore, por lo que incluimos la información de precios más arriba.

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.

7. Recursos adicionales

Problemas o comentarios sobre el codelab

Si encuentras algún problema con este Codelab, primero busca el problema antes de enviarlo. Vínculos para buscar y crear problemas nuevos:

Recursos de migración

En la siguiente tabla, encontrarás los vínculos a las carpetas del repositorio del módulo 15 (START) y el módulo 16 (FINISH). 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 15

código

N/A

Módulo 16 (este codelab)

código

(igual que Python 2)

Recursos en línea

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

Blobstore de App Engine y Cloud Storage

Plataforma de App Engine

Otra información de Cloud

Python

Videos

Licencia

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