Модуль 2. Миграция с App Engine ndb на Cloud NDB

1. Обзор

Эта серия практических занятий (самостоятельное обучение) призвана помочь разработчикам Google App Engine (Standard) модернизировать свои приложения, проведя их через ряд миграций. Наиболее важным шагом является отказ от встроенных сервисов оригинальной среды выполнения, поскольку среды выполнения следующего поколения более гибкие, предоставляя пользователям большее разнообразие вариантов сервисов. Переход на среду выполнения нового поколения позволяет проще интегрироваться с продуктами Google Cloud, использовать более широкий спектр поддерживаемых сервисов и поддерживать текущие версии языков программирования.

В этом руководстве вы узнаете, как перейти с встроенной в App Engine клиентской библиотеки ndb (Next Database) на клиентскую библиотеку Cloud NDB .

Вы узнаете, как

  • Используйте библиотеку App Engine ndb (если вы с ней не знакомы).
  • Переход с ndb на Cloud NDB
  • Дальнейший перевод вашего приложения на Python 3.

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

Опрос

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

Прочитайте только до конца. Прочитайте текст и выполните упражнения.

2. Предыстория

В модуле 1 мы перевели веб-фреймворки со встроенного в App Engine webapp2 на Flask . В этом практическом занятии мы продолжаем отказываться от встроенных сервисов App Engine, переходя с библиотеки ndb от App Engine на Google Cloud NDB .

После завершения миграции вы сможете:

  1. Переходите на Python 3 и среду выполнения App Engine нового поколения.
  2. Перейдите на Cloud Datastore (клиентская библиотека для приложений, не использующих App Engine).
  3. Создайте контейнер для своего приложения на Python 2 (или 3) и перейдите на Cloud Run.
  4. Добавьте использование очередей задач App Engine (push), а затем перейдите на Cloud Tasks.

Но мы еще не достигли цели. Завершите этот практический урок, прежде чем переходить к следующим шагам. Миграция в этом руководстве включает следующие основные этапы:

  1. Подготовка/Настройка
  2. Добавить библиотеку Cloud NDB
  3. Обновите файлы приложения

3. Подготовка/Предварительные работы

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

1. Настройка проекта

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

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

Одним из предварительных условий является наличие работающего примера приложения из Модуля 1. Используйте своё решение, если вы прошли этот урок. Вы можете пройти его сейчас (ссылка выше), или, если хотите пропустить, скопируйте репозиторий Модуля 1 (ссылка ниже).

Независимо от того, используете ли вы свой или наш код, мы НАЧНЕМ с кода Модуля 1. Этот практический пример по Модулю 2 шаг за шагом проведет вас через каждый этап, и по завершении он должен выглядеть примерно так же, как код в КОНЦЕ (включая необязательный «бонус» — перенос кода с Python 2 на Python 3):

В папке с кодом модуля STARTing Module 1 должно содержаться следующее:

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

Если вы завершили обучение по Модулю 1, у вас также будет папка lib с Flask и его зависимостями. Если у вас нет папки lib , создайте её с помощью команды pip install -t lib -r requirements.txt чтобы мы могли развернуть это базовое приложение на следующем шаге. Если у вас установлены Python 2 и 3, мы рекомендуем использовать pip2 вместо pip , чтобы избежать путаницы с Python 3.

3. (Повторное) развертывание приложения модуля 1.

Осталось выполнить следующие подготовительные шаги:

  1. При необходимости ознакомьтесь с инструментом командной строки gcloud .
  2. (При необходимости) повторно разверните код Модуля 1 в App Engine.

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

4. Обновите конфигурационные файлы (добавьте библиотеку Cloud NDB).

Многие встроенные сервисы App Engine превратились в самостоятельные продукты, и Datastore — один из них. Сегодня приложения, не относящиеся к App Engine, могут использовать Cloud Datastore . Для давних пользователей ndb команда Google Cloud создала клиентскую библиотеку Cloud NDB для взаимодействия с Cloud Datastore. Она доступна как для Python 2, так и для Python 3.

Давайте обновим файлы подтверждения, заменив App Engine ndb на Cloud NDB, а затем внесем изменения в наше приложение.

1. Обновите файл requirements.txt .

В первом модуле единственной внешней зависимостью для нашего приложения был Flask. Теперь добавим Cloud NDB. Вот как выглядел ваш файл requirements.txt в конце первого модуля:

  • ДО:
Flask==1.1.2

Для перехода с App Engine ndb требуется библиотека Cloud NDB ( google-cloud-ndb ), поэтому добавьте её пакет в requirements.txt .

  • ПОСЛЕ:
Flask==1.1.2
google-cloud-ndb==1.7.1

На момент написания этого руководства рекомендуемая версия — 1.7.1, но в файле requirements.txt в репозитории может быть указана более новая версия. Мы рекомендуем использовать последние версии каждой библиотеки, но если они не работают, вы можете откатиться к более старой версии.

Удалите папку lib , если она у вас есть и вы её не создали ранее. Теперь (пере)установите обновлённые библиотеки с помощью команды pip install -t lib -r requirements.txt , используя pip2 вместо pip , если это необходимо.

2. Обновите файл app.yaml

Добавление клиентских библиотек Google Cloud, таких как google-cloud-ndb имеет ряд требований, все они связаны с включением «встроенных» библиотек — сторонних пакетов, уже доступных на серверах Google. Их не нужно указывать в requirements.txt и не нужно копировать с помощью pip install . Единственные требования:

  1. Укажите встроенные библиотеки в app.yaml
  2. Укажите им на скопированные сторонние библиотеки, с которыми они могут работать (в lib ).

Вот начальный файл app.yaml из модуля 1:

  • ДО:
runtime: python27
threadsafe: yes
api_version: 1

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

Теперь добавьте следующие строки в app.yaml , чтобы сослаться на пару сторонних пакетов: grpcio и setuptools в новом разделе libraries :

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

Зачем использовать эти встроенные библиотеки? gRPC — это открытая RPC-платформа, используемая всеми клиентскими библиотеками Google Cloud , включая google-cloud-ndb . Библиотека grpcio — это адаптер gRPC для Python, и поэтому она необходима. Причина включения setuptools будет объяснена позже.

  • ПОСЛЕ:

После внесения вышеуказанных изменений ваш обновленный app.yaml должен выглядеть следующим образом:

runtime: python27
threadsafe: yes
api_version: 1

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

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

3. Обновите файл appengine_config.py

Инструмент pkg_resources , входящий в библиотеку setuptools , используется для обеспечения доступа встроенных сторонних библиотек к библиотекам, входящим в состав пакета . Обновите appengine_config.py , чтобы использовать pkg_resources для указания на встроенные библиотеки в lib . После внесения этих изменений весь файл должен выглядеть следующим образом:

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)

5. Обновите файлы приложения.

После завершения формальностей с конфигурационными файлами вы можете перейти с ndb на Cloud NDB. Для завершения миграции обновите импортированные библиотеки и добавьте использование управления контекстом в main.py

1. Импорт

Внесите следующие изменения в импорт файла main.py :

  • ДО
from google.appengine.ext import ndb
  • ПОСЛЕ:
from google.cloud import ndb

Переход от библиотеки App Engine к библиотеке Google Cloud иногда бывает таким же незначительным, как в этом случае. Для встроенных сервисов, которые стали полноценными продуктами Google Cloud, вы будете импортировать атрибуты из google.cloud вместо google.appengine .

2. Доступ к хранилищу данных

Для использования библиотеки Cloud NDB ваше приложение должно использовать контекстные менеджеры Python . Их назначение — «ограничивать» доступ к ресурсам таким образом, чтобы их необходимо было получить до использования. Контекстные менеджеры основаны на методе управления ресурсами, известном как распределение ресурсов при инициализации (Resource Allocation Is Initialization, RAII) . Контекстные менеджеры используются с файлами Python (которые необходимо открыть перед доступом к ним), а для обеспечения параллельного выполнения кода в « критической секции » необходимо получить « спин-блокировки ».

Аналогично, Cloud NDB требует получения контекста клиента для связи с Datastore, прежде чем можно будет выполнить какие-либо команды Datastore. Сначала создайте клиент ( ndb.Client() ), добавив ds_client = ndb.Client() в main.py сразу после инициализации Flask :

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

Команда ` with Python используется исключительно для получения контекста объекта. Любые блоки кода, обращающиеся к Datastore, следует заключать в операторы ` with .

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

  • ДО:

Вот исходный код без управления контекстом:

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

def fetch_visits(limit):
    'get most recent visits'
    return (v.to_dict() for v in Visit.query().order(
            -Visit.timestamp).fetch(limit))
  • ПОСЛЕ:

Теперь добавьте ` with ds_client.context(): и переместите код доступа к хранилищу данных в блок with :

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

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

Основное приложение драйвера остается идентичным тому, что мы использовали в Модуле 1, поскольку здесь нет кода ndb (и Cloud NDB):

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

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

6. Подведение итогов/Завершение

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

Переразверните приложение с помощью gcloud app deploy и убедитесь, что оно работает. Теперь ваш код должен соответствовать коду из репозитория модуля 2 .

Если вы начали этот цикл, не выполнив ни одного из предыдущих практических заданий, само приложение не изменится; оно регистрирует все посещения главной веб-страницы ( / ) и выглядит так после того, как вы достаточное количество раз посетите сайт:

приложение visitme

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

Необязательно: Уборка

Как насчет того, чтобы навести порядок и избежать выставления счетов до тех пор, пока вы не будете готовы перейти к следующему этапу миграции на CodeLab? Как опытные разработчики, вы, вероятно, уже знакомы с информацией о ценах App Engine .

(Необязательно): Отключить приложение

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

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

Следующие шаги

Далее у вас есть свобода действий. Выберите любой из следующих вариантов:

  • Бонус модуля 2: Перейдите к бонусной части этого руководства, чтобы изучить перенос на Python 3 и среду выполнения App Engine следующего поколения.
  • Модуль 7: Очереди задач App Engine Push (необходим, если вы используете очереди задач [push])
    • Добавляет задачи из очереди taskqueue App Engine в приложение Модуля 1.
    • В модуле 8 осуществляется подготовка пользователей к миграции в облако.
  • Модуль 4: Миграция в облако. Запуск с помощью Docker.
    • Создайте контейнер для запуска вашего приложения в Cloud Run с помощью Docker.
    • Позволяет оставаться на Python 2.
  • Модуль 5: Миграция в облако. Запуск с помощью Cloud Buildpacks.
    • Создайте контейнер для запуска вашего приложения в Cloud Run с помощью Cloud Buildpacks.
    • Вам не нужно ничего знать о Docker, контейнерах или Dockerfile .
    • Для этого необходимо предварительно перевести ваше приложение на Python 3.
  • Модуль 3:
    • Модернизация доступа к хранилищу данных из Cloud NDB в Cloud Datastore.
    • Эта библиотека используется как для приложений, работающих на Python 3 App Engine, так и для приложений, не использующих App Engine.

7. БОНУС: Переход на Python 3

Для доступа к новейшей среде выполнения и функциям App Engine мы рекомендуем перейти на Python 3. В нашем примере приложения Datastore был единственным встроенным сервисом, который мы использовали, и поскольку мы перешли с ndb на Cloud NDB, теперь мы можем использовать среду выполнения Python 3 в App Engine.

Обзор

Хотя перенос на Python 3 не входит в рамки руководства Google Cloud, эта часть практического занятия дает разработчикам представление о том, чем отличается среда выполнения Python 3 App Engine. Одна из выдающихся особенностей среды выполнения нового поколения — упрощенный доступ к сторонним пакетам; нет необходимости указывать встроенные пакеты в app.yaml , а также нет необходимости копировать или загружать невстроенные библиотеки; они устанавливаются автоматически из списка в requirements.txt .

Поскольку наш пример очень простой , а Cloud NDB совместим с Python 2-3, нет необходимости явно переносить код приложения на версию 3.x; приложение работает на версиях 2.x и 3.x без изменений, то есть в данном случае требуются только изменения в конфигурации:

  1. Упростите app.yaml , чтобы он ссылался на Python 3, и удалите сторонние библиотеки.
  2. Удалите appengine_config.py и папку lib , поскольку они больше не нужны.

Помимо main.py , файлы requirements.txt и templates/index.html остаются без изменений.

Упростите файл app.yaml

ДО:

Единственное существенное изменение в этом примере приложения — это значительное сокращение файла app.yaml . Напомним, что в конце модуля 2 в app.yaml содержался следующий текст:

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

ПОСЛЕ:

В Python 3 директивы threadsafe , api_version и libraries устарели; все приложения считаются потокобезопасными, а api_version в Python 3 не используется. Встроенные сторонние пакеты больше не устанавливаются предварительно в сервисы App Engine, поэтому libraries также устарела. Для получения дополнительной информации об этих изменениях ознакомьтесь с документацией по изменениям в app.yaml . В результате вам следует удалить все три директивы из app.yaml и обновить Python до поддерживаемой версии (см. ниже).

Необязательно: Директива использования handlers .

Кроме того, директива handlers , которая направляет трафик к приложениям App Engine, также устарела. Поскольку среда выполнения следующего поколения ожидает, что веб-фреймворки будут управлять маршрутизацией приложений, все "скрипты обработчиков" необходимо заменить на " auto ". Объединив вышеуказанные изменения, вы получите следующий файл app.yaml :

runtime: python38

handlers:
- url: /.*
  script: auto

Подробнее о script: auto можно узнать на странице документации .

Удаление директивы handlers

Поскольку handlers устарели, вы можете удалить весь этот раздел целиком, оставив app.yaml в одну строку:

runtime: python38

По умолчанию запускается веб-сервер Gunicorn WSGI , доступный для всех приложений. Если вы знакомы с gunicorn , то вот команда, которая выполняется при его запуске по умолчанию с минимальным набором файлов app.yaml :

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

Необязательно: Использование директивы entrypoint

Однако, если вашему приложению требуется определенная команда запуска, ее можно указать с помощью директивы entrypoint , в результате чего ваш app.yaml будет выглядеть следующим образом:

runtime: python38
entrypoint: python main.py

В этом примере специально запрашивается использование сервера разработки Flask вместо gunicorn . Код, запускающий сервер разработки, также необходимо добавить в ваше приложение для запуска через интерфейс 0.0.0.0 на порту 8080, добавив следующий небольшой раздел в конец файла main.py :

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

Узнайте больше о entrypoint на странице документации . Дополнительные примеры и рекомендации можно найти в документации по запуску App Engine Standard, а также в документации по запуску App Engine Flexible .

Удалите appengine_config.py и lib

Удалите файл appengine_config.py и папку lib . При переходе на Python 3 App Engine автоматически получает и устанавливает пакеты, перечисленные в requirements.txt .

Конфигурационный файл appengine_config.py используется для распознавания сторонних библиотек/пакетов, независимо от того, скопировали ли вы их самостоятельно или используете уже имеющиеся на серверах App Engine (встроенные). При переходе на Python 3 основные изменения заключаются в следующем:

  1. Запрещено включать в комплект скопированные сторонние библиотеки (перечисленные в requirements.txt ).
  2. pip install в папку lib запрещена, то есть папка lib вообще не существует.
  3. В app.yaml отсутствует список встроенных сторонних библиотек.
  4. Нет необходимости ссылаться на сторонние библиотеки в приложении, поэтому файл appengine_config.py не нужен.

Достаточно перечислить все необходимые сторонние библиотеки в файле requirements.txt .

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

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

Поздравляем с завершением бонусного этапа модуля 2! Ознакомьтесь с документацией по подготовке конфигурационных файлов для среды выполнения Python 3. Наконец, просмотрите (предыдущую) страницу «Сводка/Очистка» для получения информации о дальнейших шагах и очистке.

Подготовка вашей заявки

Когда придёт время миграции вашего приложения, вам придётся перенести файл main.py и другие файлы приложения на версию 3.x, поэтому лучшей практикой будет постараться сделать ваше приложение версии 2.x максимально "обратно совместимым".

В интернете есть множество ресурсов, которые помогут вам в этом, но вот несколько ключевых советов:

  1. Убедитесь, что все зависимости приложения полностью совместимы с версией 3.x.
  2. Убедитесь, что ваше приложение работает как минимум на версии 2.6 (предпочтительно 2.7).
  3. Убедитесь, что приложение проходит весь набор тестов (и имеет как минимум 80% покрытия).
  4. Используйте библиотеки совместимости, такие как six , Future и/или Modernize.
  5. Изучите ключевые различия между версиями 2.x и 3.x, препятствующие обратной совместимости.
  6. Любые операции ввода-вывода, скорее всего, приведут к несовместимости Unicode и байтовых строк.

Демонстрационное приложение было разработано с учетом всего этого, поэтому оно работает на версиях 2.x и 3.x сразу после установки, чтобы мы могли сосредоточиться на демонстрации того, что необходимо изменить для использования платформы следующего поколения.

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

Проблемы/обратная связь по модулю миграции App Engine на Codelabs

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

Миграционные ресурсы

Ссылки на папки репозитория для Модуля 1 (НАЧАЛО) и Модуля 2 (ЗАВЕРШЕНИЕ) можно найти в таблице ниже. К ним также можно получить доступ из репозитория для всех миграций кода App Engine, которые можно клонировать или загрузить в виде ZIP-файла.

Кодлаб

Python 2

Python 3

Модуль 1

код

(н/д)

Модуль 2

код

код

Ресурсы App Engine

Ниже приведены дополнительные ресурсы, касающиеся данной конкретной миграции: