Как перейти с хранилища BLOB-объектов App Engine на Cloud Storage (модуль 16)

1. Обзор

Серия практических работ Serverless Migration Station (самостоятельные практические руководства) и связанные с ними видео призваны помочь разработчикам бессерверных решений Google Cloud модернизировать свои приложения, проведя их через одну или несколько миграций, в первую очередь за счет отказа от устаревших сервисов. Это повысит переносимость приложений, а также предоставит вам больше возможностей и гибкости, что позволит интегрировать и использовать более широкий спектр продуктов Cloud и упростит переход на более новые версии языков. Изначально мы ориентировались на первых пользователей Cloud, в основном разработчиков App Engine (стандартная среда), но эта серия достаточно широка, чтобы включать другие бессерверные платформы, такие как Cloud Functions и Cloud Run, или другие, если применимо.

В этой практической работе показано, как перейти с хранилища BLOB-объектов App Engine на Cloud Storage. Также неявный перенос выполняется из следующих источников:

Дополнительные пошаговые инструкции можно найти в модулях, посвященных переносу.

Вы научитесь:

  • Добавьте использование API/библиотеки хранилища BLOB-объектов App Engine
  • Хранение загруженных пользователями файлов в сервисе Blobstore.
  • Подготовка к переходу на Cloud Storage

Что вам понадобится

Опрос

Как вы будете использовать это руководство?

Просто прочитаю Прочитаю и выполню упражнения

Как бы вы оценили свой опыт работы с Python?

Начинающий Средний Продвинутый

Как бы вы оценили свой опыт использования сервисов Google Cloud?

Начинающий Средний Продвинутый

2. Фон

В этой практической работе мы возьмем пример приложения из модуля 15 и покажем, как перейти с хранилища BLOB-объектов (и NDB) на Cloud Storage (и Cloud NDB). В процессе переноса заменяются зависимости от устаревших пакетных сервисов App Engine, что позволяет при желании перенести приложения на другую бессерверную платформу Cloud или другую платформу хостинга.

Этот перенос требует немного больше усилий, чем другие переносы в этой серии. Blobstore зависит от исходной инфраструктуры webapp, поэтому в примере приложения используется инфраструктура webapp2, а не Flask. В этом руководстве рассматривается перенос в Cloud Storage, Cloud NDB, Flask и Python 3.

Приложение по-прежнему регистрирует посещения конечных пользователей и показывает десять последних, но в предыдущей практической работе (модуль 15) была добавлена новая функция для использования Blobstore: приложение предлагает конечным пользователям загрузить артефакт (файл), соответствующий их посещению. Пользователи могут сделать это или нажать "Пропустить", чтобы отказаться. Независимо от решения пользователя, на следующей странице отображаются те же данные, что и в предыдущих версиях этого приложения, – последние посещения. Ещё одна особенность заключается в том, что посещения с соответствующими артефактами содержат ссылку "Просмотр" для отображения артефакта посещения. В этой практической работе мы реализуем упомянутые выше переносы, сохранив описанную функциональность.

3. Настройка и подготовка

Прежде чем перейти к основной части руководства, давайте настроим проект, получим код и развернем базовое приложение, чтобы убедиться, что мы начали с рабочего кода.

1. Настроить проект

Если вы уже развернули приложение модуля 15, рекомендуем повторно использовать тот же проект (и код). Вы также можете создать новый проект или использовать другой существующий. Убедитесь, что у проекта есть активный платежный аккаунт и включен App Engine.

2. Получить базовый пример приложения

Для выполнения этой практической работы вам понадобится пример приложения из модуля 15. Если у вас его нет, скачайте его из папки START модуля 15 (ссылка ниже). В этой практической работе мы пошагово разберем, как это сделать. В результате у вас получится код, похожий на тот, что находится в папке FINISH модуля 16.

Каталог исходных файлов модуля 15 должен выглядеть следующим образом:

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

Файл main-gcs.py – это альтернативная версия файла main.py из модуля 15, позволяющая выбрать сегмент Cloud Storage, отличный от URL, назначенного приложению по умолчанию на основе идентификатора проекта: PROJECT_ID.appspot.com. Этот файл не используется в практической работе (модуль 16), но при желании к нему можно применить аналогичные методы переноса.

3. Разверните базовое приложение (повторно)

Что нужно сделать сейчас:

  1. Освежите в памяти информацию об инструменте командной строки gcloud.
  2. Повторно разверните пример приложения с помощью gcloud app deploy
  3. Убедитесь, что приложение работает в App Engine без проблем.

После того как вы выполните эти действия и убедитесь, что приложение Module 15 работает, На первой странице пользователям предлагается загрузить файл с данными о посещении или отказаться от этого, нажав кнопку "Пропустить".

f5b5f9f19d8ae978.png

После того как пользователь загрузит файл или пропустит этот шаг, приложение отобразит привычную страницу "Последние посещения":

f5ac6b98ee8a34cb.png

Если в посещении есть артефакт, справа от временной метки посещения будет ссылка "Просмотр", позволяющая посмотреть или скачать артефакт. Убедившись, что приложение работает, вы можете перейти с устаревших сервисов App Engine (webapp2, NDB, Blobstore) на современные альтернативы (Flask, Cloud NDB, Cloud Storage).

4. Обновите файлы конфигурации

Для обновленной версии приложения используются три файла конфигурации. Необходимо выполнить следующие задачи:

  1. Обновите необходимые встроенные сторонние библиотеки в app.yaml и оставьте возможность перехода на Python 3.
  2. Добавьте элемент requirements.txt, в котором укажите все необходимые библиотеки, не являющиеся встроенными.
  3. Добавьте appengine_config.py, чтобы приложение поддерживало как встроенные, так и невстроенные сторонние библиотеки.

app.yaml

Отредактируйте файл app.yaml, обновив раздел libraries. Удалите jinja2 и добавьте grpcio, setuptools и ssl. Выберите последнюю версию, доступную для всех трех библиотек. Также добавьте директиву Python 3 runtime, но закомментируйте ее. После этого окно должно выглядеть следующим образом (если вы выбрали Python 3.9):

BEFORE:

runtime: python27
threadsafe: yes
api_version: 1

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

libraries:
- name: jinja2
  version: latest

ПОСЛЕ

#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

Изменения в основном касаются встроенных библиотек Python 2, доступных на серверах App Engine (поэтому вам не нужно самостоятельно упаковывать их). Мы удалили Jinja2, потому что он поставляется с Flask, который мы добавим в reqs.txt. При использовании клиентских библиотек Google Cloud, например для Cloud NDB и Cloud Storage, требуются grpcio и setuptools. Наконец, для самого Cloud Storage требуется библиотека ssl. Закомментированная директива среды выполнения вверху предназначена для того, чтобы вы могли перенести это приложение на Python 3. Мы рассмотрим эту тему в конце руководства.

requirements.txt

Добавьте файл requirements.txt, для которого требуются фреймворк Flask и клиентские библиотеки Cloud NDB и Cloud Storage (ни одна из них не является встроенной). Создайте файл со следующим содержимым:

flask
google-cloud-ndb
google-cloud-storage

Среда выполнения Python 2 App Engine требует самостоятельного связывания невстроенных сторонних библиотек, поэтому выполните следующую команду, чтобы установить эти библиотеки в папку lib:

pip install -t lib -r requirements.txt

Если на вашем компьютере для разработки установлены обе версии Python, возможно, вам потребуется использовать команду pip2, чтобы получить версии библиотек для Python 2. После перехода на Python 3 вам больше не нужно будет самостоятельно упаковывать библиотеки.

appengine_config.py

Добавьте файл appengine_config.py, поддерживающий встроенные и невстроенные сторонние библиотеки. Создайте файл со следующим содержимым:

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)

Выполненные действия должны быть похожи или идентичны действиям, описанным в разделе Установка библиотек для приложений Python 2 документации по App Engine. В частности, содержимое файла appengine_config.py должно соответствовать тому, что указано на шаге 5.

Работа с файлами конфигурации завершена, поэтому давайте перейдем к приложению.

5. Изменение файлов приложения

Импорт

Первый набор изменений для main.py включает замену всех заменяемых элементов. Вот что изменится:

  1. webapp2 заменяется на Flask.
  2. Вместо Jinja2 из webapp2_extras используйте Jinja2, который поставляется с Flask.
  3. Хранилище BLOB-объектов App Engine и NDB заменены на Cloud NDB и Cloud Storage
  4. Обработчики Blobstore в webapp заменяются комбинацией стандартного библиотечного модуля io, Flask и утилит werkzeug.
  5. По умолчанию Blobstore записывает данные в сегмент Cloud Storage, названный в честь URL вашего приложения (PROJECT_ID.appspot.com). Поскольку мы переносим данные в клиентскую библиотеку Cloud Storage, google.auth используется для получения идентификатора проекта, чтобы указать точно такое же имя сегмента. (Вы можете изменить название сегмента, поскольку оно больше не задано в коде.)

BEFORE:

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

Чтобы внести изменения, перечисленные выше, замените текущий раздел импорта в файле main.py на приведенный ниже фрагмент кода.

ПОСЛЕ

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

Инициализация и ненужная поддержка Jinja2

Следующий блок кода, который нужно заменить, – это BaseHandler, указывающий на использование Jinja2 из webapp2_extras. Это не нужно, потому что Jinja2 поставляется с Flask и является его механизмом шаблонов по умолчанию, поэтому удалите его.

В модуле 16 создайте экземпляры объектов, которых не было в старом приложении. Это включает инициализацию приложения Flask и создание API-клиентов для Cloud NDB и Cloud Storage. Наконец, мы собираем название сегмента Cloud Storage, как описано выше в разделе об импорте. Вот как это выглядит до и после обновления:

BEFORE:

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

ПОСЛЕ

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

Обновить доступ к хранилищу данных

Cloud NDB в основном совместим с App Engine NDB. Одно из различий, о котором мы уже говорили, – необходимость в API-клиенте. Другое отличие заключается в том, что во втором случае доступ к Datastore должен контролироваться менеджером контекста Python API-клиента. По сути, это означает, что все вызовы доступа к Datastore с использованием клиентской библиотеки Cloud NDB могут происходить только в блоках Python with.

Это одно изменение. Другое заключается в том, что Blobstore и его объекты, например BlobKey, не поддерживаются Cloud Storage, поэтому измените file_blob на ndb.StringProperty. Ниже приведены класс модели данных и обновленные функции store_visit() и fetch_visits(), отражающие эти изменения.

BEFORE:

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)

ПОСЛЕ

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)

Ниже показано, как изменился интерфейс.

a8f74ca392275822.png

Обновление обработчиков

Обработчик загрузки

Обработчики в webapp2 – это классы, а во Flask – функции. Вместо метода HTTP-глагола Flask использует глагол для декорирования функции. Хранилище BLOB-объектов и его обработчики webapp заменяются функциями Cloud Storage, а также Flask и его утилитами:

BEFORE:

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)

ПОСЛЕ

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

Примечания:

  • Вместо blob_id объекты файлов теперь идентифицируются по названию файла (fname), если оно есть, и по None в противном случае (пользователь отказался от загрузки файла).
  • Обработчики Blobstore абстрагировали процесс загрузки от пользователей, но Cloud Storage этого не делает, поэтому вы можете увидеть добавленный код, который задает объект blob и местоположение (сегмент) файла, а также вызов, который выполняет фактическую загрузку. (upload_from_file()).
  • webapp2 использует таблицу маршрутизации в нижней части файла приложения, а маршруты Flask находятся в каждом декорированном обработчике.
  • Оба обработчика завершают свою работу, перенаправляя пользователя на главную страницу ( /) и сохраняя запрос POST с кодом возврата HTTP 307.

Обработчик скачивания

Обновление обработчика скачивания выполняется аналогично обработчику загрузки, только кода намного меньше. Замените функции Blobstore и webapp эквивалентами Cloud Storage и Flask:

BEFORE:

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)

ПОСЛЕ

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

Примечания к этому обновлению:

  • Flask декорирует функции обработчика с их маршрутом, а webapp делает это в таблице маршрутизации внизу. Обратите внимание на синтаксис сопоставления с образцом в (('/view/([^/]+)?') и Flask ('/view/<path:fname>').
  • Как и в случае с обработчиком загрузки, на стороне Cloud Storage требуется немного больше работы для функциональности, абстрагированной обработчиками Blobstore, а именно для идентификации рассматриваемого файла (blob) и явной загрузки двоичного файла по сравнению с одним вызовом метода send_blob() обработчика Blobstore.
  • В обоих случаях, если объект не найден, пользователь получает ошибку HTTP 404.

Основной обработчик

Окончательные изменения в основном приложении происходят в основном обработчике. Методы HTTP-глаголов webapp2 заменены одной функцией, которая объединяет их возможности. Замените класс MainHandler функцией root() и удалите таблицу маршрутизации webapp2, как показано ниже.

BEFORE:

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)

ПОСЛЕ

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

Вместо отдельных методов get() и post() они по сути являются оператором if-else в root(). Кроме того, поскольку root() – это одна функция, для отрисовки шаблона как для GET, так и для POST требуется только один вызов, тогда как в webapp2 это невозможно.

Ниже показано, как будет выглядеть main.py после второго и последнего этапа изменений.

5ec38818c32fec2.png

Улучшение обратной совместимости (необязательно)

Решение, которое мы создали, работает отлично, но только если вы начинаете с нуля и у вас нет файлов, созданных Blobstore. Поскольку мы обновили приложение, чтобы идентифицировать файлы по названию файла вместо BlobKey, завершенное приложение Модуля 16 как есть не сможет просматривать файлы хранилища BLOB-объектов. Другими словами, мы внесли изменение, несовместимое с предыдущими версиями. Мы представляем альтернативную версию main.py под названием main-migrate.py (находится в репозитории), которая пытается устранить этот пробел.

Первое "расширение" для поддержки файлов, созданных Blobstore, – это модель данных, которая содержит BlobKeyProperty (в дополнение к StringProperty для файлов, созданных 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()

Свойство file_blob будет использоваться для идентификации файлов, созданных Blobstore, а file_gcs – для файлов Cloud Storage. Теперь при создании новых посещений явно сохраняйте значение в file_gcs вместо file_blob, чтобы store_visit выглядело немного иначе:

BEFORE:

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

При получении данных о последних посещениях нормализуйте их, прежде чем отправлять в шаблон:

BEFORE:

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

ПОСЛЕ

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

Затем подтвердите наличие file_blob или file_gcs (или их отсутствие). Если файл доступен, выберите существующий и используйте его идентификатор (BlobKey для файлов, созданных в Blobstore, или название файла для файлов, созданных в Cloud Storage). Под файлами, созданными в Cloud Storage, мы подразумеваем файлы, созданные с помощью клиентской библиотеки Cloud Storage. Blobstore также записывает данные в Cloud Storage, но в этом случае это будут файлы, созданные Blobstore.

Теперь самое главное: что это за функция etl_visits(), которая используется для нормализации или ETL (извлечения, преобразования и загрузки) данных для конечного пользователя? Кнопка выглядит так:

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]

Вероятно, он выглядит так, как вы ожидали: код перебирает все посещения и для каждого посещения дословно берет данные о посетителе и временной метке, а затем проверяет, существует ли file_gcs или file_blob, и если да, выбирает один из них (или None, если ни один из них не существует).

Ниже показано, чем отличаются main.py и main-migrate.py.

718b05b2adadb2e1.png

Если вы начинаете с нуля и у вас нет файлов, созданных Blobstore, используйте main.py. Если же вы переходите на Cloud Storage и хотите поддерживать файлы, созданные как Blobstore, так и Cloud Storage, посмотрите пример main-migrate.py, чтобы узнать, как действовать в такой ситуации и спланировать перенос для своих приложений. При выполнении сложных переносов могут возникать особые случаи, поэтому этот пример призван показать большую близость к модернизации реальных приложений с реальными данными.

6. Сводка/очистка

В этом разделе мы завершим практическую работу, развернув приложение и проверив, что оно работает правильно и выводит нужные данные. После проверки приложения выполните необходимые действия по очистке и определите дальнейшие шаги.

Развертывание и проверка приложения

Прежде чем повторно развернуть приложение, запустите pip install -t lib -r requirements.txt, чтобы получить сторонние библиотеки в папке lib. Если вы хотите запустить решение с обратной совместимостью, сначала переименуйте main-migrate.py в main.py. Теперь запустите gcloud app deploy и убедитесь, что приложение работает так же, как и в модуле 15. Экран формы выглядит следующим образом:

f5b5f9f19d8ae978.png

Страница с последними посещениями выглядит так:

f5ac6b98ee8a34cb.png

Поздравляем! Вы завершили практическую работу по замене хранилища BLOB-объектов App Engine на Cloud Storage, NDB App Engine на Cloud NDB и webapp2 на Flask. Теперь ваш код должен соответствовать коду в папке FINISH (Module 16). В этой папке также есть альтернативный файл main-migrate.py.

Переход на Python 3

Закомментированная директива Python 3 runtime в верхней части файла app.yaml – это все, что нужно для переноса этого приложения в Python 3. Исходный код уже совместим с Python 3, поэтому вносить в него изменения не нужно. Чтобы развернуть его как приложение Python 3, выполните следующие действия:

  1. Раскомментируйте директиву runtime Python 3 в верхней части файла app.yaml.
  2. Удалите все остальные строки в файле app.yaml.
  3. Удалите файл appengine_config.py. (не используется в среде выполнения Python 3)
  4. Удалите папку lib, если она существует. (не требуется для среды выполнения Python 3)

Организовать

Общие

Если вы закончили работу, рекомендуем отключить приложение App Engine, чтобы избежать непредвиденных расходов. Однако если вы хотите продолжить тестирование или эксперименты, платформа App Engine предоставляет бесплатную квоту, и пока вы не превысите этот уровень использования, плата взиматься не будет. Это касается вычислений, но может взиматься плата и за использование сервисов App Engine. Подробную информацию вы найдете на странице с ценами. Если в переносе задействованы другие сервисы Cloud, они оплачиваются отдельно. В любом случае, если применимо, ознакомьтесь с разделом "Особенности этой практической работы" ниже.

Обратите внимание, что развертывание на бессерверной вычислительной платформе Google Cloud, такой как App Engine, влечет за собой небольшие расходы на сборку и хранение. У Cloud Build и Cloud Storage есть собственные бесплатные квоты. Хранение этого изображения занимает часть квоты. Однако в вашем регионе бесплатный план может быть недоступен, поэтому следите за использованием хранилища, чтобы минимизировать возможные расходы. В частности, вам нужно проверить следующие папки Cloud Storage:

  • 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
  • Ссылки на хранилище выше зависят от вашего PROJECT_ID и *LOC*ation, например us, если ваше приложение размещено в США.

Если вы не планируете продолжать работу с этим приложением или другими практическими работами по переносу и хотите удалить все полностью, закройте проект.

Особенности этой практической работы

Сервисы, перечисленные ниже, используются только в этой практической работе. Дополнительную информацию можно найти в документации по каждому продукту:

Обратите внимание, что если вы перешли с модуля 15 на модуль 16, у вас по-прежнему будут данные в Blobstore, поэтому мы включили информацию о ценах на него выше.

Дальнейшие действия

Помимо этого руководства, вы можете ознакомиться с другими модулями, посвященными переходу с устаревших пакетных сервисов:

  • Модуль 2. Переход с App Engine (ndb) на Cloud NDB
  • Модули 7–9. Переход с задач с отправкой из очереди задач App Engine на Cloud Tasks.
  • Модули 12–13. Переход с App Engine Memcache на Cloud Memorystore.
  • Модули 18–19. Переход с очереди задач App Engine (задачи с извлечением) на Cloud Pub/Sub.

App Engine – не единственная бессерверная платформа в Google Cloud. Если у вас есть небольшое приложение App Engine или приложение с ограниченной функциональностью, которое вы хотите превратить в автономный микросервис, или если вы хотите разбить монолитное приложение на несколько повторно используемых компонентов, это веские причины подумать о переходе на Cloud Functions. Если контейнеризация стала частью рабочего процесса разработки приложений, особенно если она состоит из конвейера CI/CD (непрерывная интеграция/непрерывная поставка или развертывание), рассмотрите возможность перехода на Cloud Run. Эти сценарии рассматриваются в следующих модулях:

  • Переход с App Engine на Cloud Functions: см. модуль 11.
  • Перейдите с App Engine на Cloud Run. О том, как контейнеризировать приложение с помощью Docker, рассказывается в модуле 4, а о том, как сделать это без контейнеров, знаний о Docker и Dockerfile, – в модуле 5.

Переход на другую бессерверную платформу необязателен. Прежде чем вносить изменения, рекомендуем рассмотреть оптимальные варианты для ваших приложений и сценариев использования.

Независимо от того, какой модуль миграции вы выберете, все материалы Serverless Migration Station (практические работы, видео, исходный код, если он доступен) можно найти в общедоступном хранилище. В файле README репозитория также содержатся рекомендации по выбору модулей переноса и порядку их использования.

7. Дополнительные ресурсы

Проблемы с практическими работами/отзывы о них

Если вы обнаружите проблемы в этой практической работе, сначала поищите информацию о них, прежде чем отправлять сообщение. Ссылки для поиска и создания новых проблем:

Информация о переносе данных

Ссылки на папки репозитория для модуля 15 (НАЧАЛО) и модуля 16 (КОНЕЦ) можно найти в таблице ниже. Их также можно найти в репозитории для всех практических работ по переносу App Engine, который можно клонировать или скачать в виде ZIP-файла.

Практическая работа

Python 2

Python 3

Модуль 15

code

–

Модуль 16 (эта практическая работа)

code

(как в Python 2)

Ресурсы в интернете

Ниже приведены онлайн-ресурсы, которые могут быть полезны для этого руководства:

Хранилище BLOB-объектов App Engine и Cloud Storage

Платформа App Engine

Другая информация о Cloud

Python

Видео

Лицензия

Эта работа лицензирована в соответствии с лицензией Creative Commons Attribution 2.0 Generic License.