Модуль 3. Миграция с Google Cloud NDB на Cloud Datastore

1. Обзор

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

Этот необязательный учебный материал показывает разработчикам, как перейти с Cloud NDB на Cloud Datastore в качестве клиентской библиотеки для взаимодействия со службой Datastore. Разработчики, предпочитающие NDB, могут остаться с ним, поскольку он совместим с Python 3, поэтому этот переход является необязательным. Этот переход предназначен только для тех, кто хочет создать согласованную кодовую базу и общие библиотеки с другими приложениями, уже использующими Cloud Datastore. Это объясняется в разделе «Введение».

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

  • Используйте Cloud NDB (если вы с ним не знакомы).
  • Миграция с Cloud NDB на Cloud Datastore
  • Дальнейший перевод вашего приложения на Python 3.

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

  • Проект на платформе Google Cloud Platform с активным платежным аккаунтом GCP.
  • Базовые навыки работы с Python.
  • Практические навыки работы с основными командами Linux.
  • Базовые знания разработки и развертывания приложений на платформе App Engine.
  • Рабочее приложение Module 2 App Engine 2.x или 3.x.

Опрос

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

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

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

Хотя Cloud NDB — отличное решение для хранения данных для опытных разработчиков App Engine и помогает при переходе на Python 3, это не единственный способ доступа к Datastore для разработчиков App Engine. Когда в 2013 году Datastore от App Engine стал самостоятельным продуктом — Google Cloud Datastore , — была создана новая клиентская библиотека , чтобы все пользователи могли использовать Datastore.

Разработчикам, использующим Python 3 App Engine и не использующим его, рекомендуется использовать Cloud Datastore (а не Cloud NDB). Разработчикам Python 2 App Engine рекомендуется перейти с ndb на Cloud NDB и затем перенести код на Python 3 оттуда, но они также могут выбрать дальнейший переход на Cloud Datastore. Это логичное решение, особенно для разработчиков, чей код уже использует Cloud Datastore, например, упомянутых выше, и которые хотят создать общие библиотеки для всех своих приложений. Повторное использование кода является лучшей практикой, как и согласованность кода, и оба эти фактора способствуют общему снижению затрат на обслуживание, как это суммировано здесь:

Миграция с Cloud NDB на Cloud Datastore

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

This migration features these primary steps:

  1. Подготовка/Настройка
  2. Замените Cloud NDB на клиентские библиотеки Cloud Datastore.
  3. Обновить приложение

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

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

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

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

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

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

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

Python 2

Структура каталога файлов модуля 2 Python (ваших или наших) должна выглядеть следующим образом:

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

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

Python 3

Структура каталога файлов модуля 2 Python 3 (ваших или наших) должна выглядеть следующим образом:

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

Ни lib , ни appengine_config.py не используются для Python 3.

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

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

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

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

4. Замените Cloud NDB на клиентские библиотеки Cloud Datastore.

Единственное изменение в конфигурации — это незначительная замена пакетов в файле requirements.txt .

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

После завершения модуля 2 ваш файл requirements.txt выглядел следующим образом:

  • ДО (Python 2 и 3):
Flask==1.1.2
google-cloud-ndb==1.7.1

Обновите requirements.txt , заменив библиотеку Cloud NDB ( google-cloud-ndb ) на последнюю версию библиотеки Cloud Datastore ( google-cloud-datastore ), оставив запись для Flask без изменений, учитывая, что последняя версия Cloud Datastore, совместимая с Python 2, — 1.15.3:

  • ПОСЛЕ (Python 2):
Flask==1.1.2
google-cloud-datastore==1.15.3
  • ПОСЛЕ (Python 3):
Flask==1.1.2
google-cloud-datastore==2.1.0

Имейте в виду, что репозиторий обновляется чаще, чем этот учебный материал, поэтому файл requirements.txt может содержать более новые версии. Мы рекомендуем использовать последние версии каждой библиотеки, но если они не работают, вы можете откатиться к более старой версии. Указанные выше номера версий являются последними на момент последнего обновления этого учебного пособия.

2. Другие конфигурационные файлы

Остальные конфигурационные файлы, app.yaml и appengine_config.py , должны остаться без изменений по сравнению с предыдущим этапом миграции:

  • app.yaml по-прежнему должны быть ссылки на сторонние пакеты grpcio и setuptools .
  • appengine_config.py по-прежнему должен указывать pkg_resources и google.appengine.ext.vendor на сторонние ресурсы в lib .

Теперь перейдём к файлам приложения.

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

В template/index.html изменений нет, но есть несколько обновлений для main.py

1. Импорт

The starting code for the import section should look as follows:

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

Замените импорт google.cloud.ndb на импорт для Cloud Datastore: google.cloud.datastore . Поскольку клиентская библиотека Datastore не поддерживает автоматическое создание поля метки времени в сущности, также импортируйте модуль datetime из стандартной библиотеки, чтобы создать его вручную. По соглашению, импорт из стандартной библиотеки осуществляется выше импорта из сторонних пакетов. После внесения этих изменений должно получиться следующее:

  • ПОСЛЕ:
from datetime import datetime
from flask import Flask, render_template, request
from google.cloud import datastore

2. Инициализация и модель данных

После инициализации Flask, пример приложения из Модуля 2, создающий класс модели данных NDB и его поля, выглядит следующим образом:

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

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

В библиотеке Cloud Datastore нет такого класса, поэтому удалите объявление класса Visit . Вам по-прежнему нужен клиент для взаимодействия с Datastore, поэтому измените ndb.Client() на datastore.Client() . Библиотека Datastore более «гибкая», позволяя создавать сущности без предварительного объявления их структуры, как в NDB. После этого обновления эта часть файла main.py должна выглядеть так:

  • ПОСЛЕ:
app = Flask(__name__)
ds_client = datastore.Client()

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

Переход на Cloud Datastore требует изменения способа создания, хранения и запроса сущностей Datastore (на уровне пользователя). Для ваших приложений сложность этой миграции зависит от сложности кода Datastore. В нашем примере приложения мы постарались максимально упростить обновление. Вот наш исходный код:

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

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

В Cloud Datastore создайте универсальную сущность, идентифицируя сгруппированные объекты в вашей сущности с помощью «ключа». Создайте запись данных с помощью объекта JSON ( dict Python) пар ключ-значение, а затем запишите её в Datastore с помощью ожидаемого метода put() . Запросы в Datastore аналогичны, но проще. Здесь вы можете увидеть, чем отличается эквивалентный код Datastore:

  • ПОСЛЕ:
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)

Обновите тела функций store_visit() и fetch_visits() , как указано выше, сохранив их сигнатуры идентичными предыдущей версии. В основной обработчик root() никаких изменений не внесено. После внесения этих изменений ваше приложение готово к использованию Cloud Datastore и тестированию.

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

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

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

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

приложение visitme

Поздравляем с завершением этого практического занятия по модулю 3! Теперь вы знаете, что можете использовать как клиентские библиотеки Cloud NDB , так и Cloud Datastore для доступа к Datastore. Перейдя на последнюю, вы получите преимущества общих библиотек, общего кода и повторного использования кода для обеспечения согласованности, а также снижения затрат на обслуживание.

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

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

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

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

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

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

Далее вы можете ознакомиться с модулями миграции:

  • Бонус модуля 3: Перейдите к бонусному разделу, чтобы узнать, как перенести приложение на Python 3 и среду выполнения App Engine следующего поколения.
  • Module 7: App Engine Push Task Queues (required if you use [push] Task Queues)
    • Добавляет задачи из очереди taskqueue App Engine в приложение Модуля 1.
    • В модуле 8 осуществляется подготовка пользователей к миграции в облако.
  • Модуль 4: Миграция в облако. Запуск с помощью Docker.
    • Создайте контейнер для запуска вашего приложения в Cloud Run с помощью Docker.
    • Позволяет оставаться на Python 2.
  • Модуль 5: Миграция в облако. Запуск с помощью Cloud Buildpacks.
    • Создайте контейнер для запуска вашего приложения в Cloud Run с помощью Cloud Buildpacks.
    • Знания о Docker, контейнерах или Dockerfile не требуются.
    • Для этого необходимо предварительно перевести ваше приложение на Python 3.
  • Модуль 6: Миграция в Cloud Firestore
    • Перейдите на Cloud Firestore, чтобы получить доступ к функциям Firebase.
    • Хотя Cloud Firestore поддерживает Python 2, данный практический пример доступен только на Python 3.

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 Datastore совместим с Python 2-3, нет необходимости явно переносить код приложения на версию 3.x: приложение работает на версиях 2.x и 3.x без изменений, то есть в данном случае требуются только изменения в конфигурации:

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

Файлы приложения main.py и templates/index.html остаются без изменений.

Обновите requirements.txt

Последняя версия Cloud Datastore, поддерживающая Python 2, — 1.15.3. Обновите requirements.txt , указав последнюю версию для Python 3 (возможно, она уже новее). На момент написания этого руководства последняя версия была 2.1.0, поэтому отредактируйте эту строку так, чтобы она выглядела следующим образом (или в соответствии с последней версией):

google-cloud-datastore==2.1.0

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

ДО:

Единственное существенное изменение в этом примере приложения — это значительное сокращение файла app.yaml . Напомним, что в конце модуля 3 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 можно узнать на странице справочника файла app.yaml .

Удаление директивы 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.yaml . Дополнительные примеры и рекомендации можно найти в документации по запуску стандартной среды App Engine, а также в документации по запуску гибкой среды App Engine .

Удалите 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 из модуля 3. Чтобы наглядно увидеть различия с Python 2, сравните код с его версией на Python 2 .

Поздравляем с завершением бонусного шага в Модуле 3! Ознакомьтесь с документацией по подготовке конфигурационных файлов для среды выполнения 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

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

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

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

Кодлаб

Python 2

Python 3

Модуль 2

код

код

Модуль 3

код

код

Ресурсы App Engine

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