Модуль 1. Миграция с App Engine webapp2 на Flask

1. Обзор

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

В этом первоначальном руководстве показаны первые шаги миграции для модернизации веб-платформы в приложениях App Engine: переход с webapp2 на Flask . В своем приложении вы можете использовать любую веб-инфраструктуру, поддерживающую маршрутизацию, но в этом руководстве мы используем Flask, поскольку он широко используется сообществом.

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

  • Используйте сторонние библиотеки (встроенные или другие)
  • Обновить файлы конфигурации
  • Перенос простого приложения из webapp2 в Flask

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

Опрос

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

Только прочитай это Прочитайте его и выполните упражнения.

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

Платформа webapp была включена в комплект, когда App Engine впервые был запущен на Python 2.5 в 2008 году. Спустя годы она была заменена преемником webapp2 , когда в 2013 году среда выполнения 2.7 объявила устаревшей версию 2.5 .

Хотя webapp2 (см. документацию ) все еще существует и может использоваться вне App Engine в качестве веб-платформы, совместимой с WSGI, он не выполняет собственную маршрутизацию пользовательских запросов к соответствующему коду в приложении. Вместо этого он полагается на App Engine, файлы конфигурации и разработчика для выполнения маршрутизации веб-трафика к соответствующим «обработчикам». Более того, основные преимущества webapp2 неразрывно связаны со встроенными службами App Engine, что фактически делает его устаревшим, даже несмотря на то , что он работает на Python 3 (см. также связанную проблему ).

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

Вот основные шаги для этой миграции:

  1. Настройка/Предварительная работа
  2. Добавить стороннюю библиотеку Flask
  3. Обновить файлы приложения
  4. Обновить файл HTML-шаблона

3. Настройка/Предварительная работа

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

1. Проект установки

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

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

Репозиторий миграции GAE содержит весь необходимый вам код. Клонируйте его или загрузите ZIP-файл. Работа с этим руководством вы начнете с кода в папке «Модуль 0» (START), а по завершении обучения ваш код должен соответствовать папке «Модуль 1» (FINISH). Если нет, проверьте различия, чтобы перейти к следующей лабораторной работе.

В папке «Модуль 0» должны быть файлы, которые выглядят следующим образом, как показано с помощью команды POSIX ls :

$ ls
app.yaml        index.html      main.py

3. (Повторно) Ознакомьтесь с командами gcloud

Если на вашем компьютере еще нет команды gcloud , установите Google Cloud SDK и убедитесь, что gcloud доступен как часть вашего пути выполнения, а также ознакомьтесь со следующими командами gcloud :

  1. gcloud components update — обновите Google Cloud SDK
  2. gcloud auth login — войдите в свою учетную запись
  3. gcloud config list — список настроек конфигурации проекта GCP.
  4. gcloud config set project PROJECT_ID — установить идентификатор проекта GCP
  5. gcloud app deploy — разверните приложение App Engine.

Если вы в последнее время не занимались разработкой App Engine с помощью gcloud , вам следует выполнить первые четыре команды (#1–#4), чтобы настроиться, прежде чем переходить к следующим шагам. Давайте сделаем краткий обзор этих команд.

Во-первых, gcloud components update гарантирует, что у вас установлена ​​последняя версия Cloud SDK. Запуск этой команды должен дать результат, подобный следующему:

$ gcloud components update

Your current Cloud SDK version is: 317.0.0
You will be upgraded to version: 318.0.0

┌──────────────────────────────────────────────────┐
│        These components will be updated.         │
├──────────────────────────┬────────────┬──────────┤
│           Name           │  Version   │   Size   │
├──────────────────────────┼────────────┼──────────┤
│ Cloud SDK Core Libraries │ 2020.11.06 │ 15.5 MiB │
│ gcloud cli dependencies  │ 2020.11.06 │ 10.6 MiB │
└──────────────────────────┴────────────┴──────────┘

The following release notes are new in this upgrade.
Please read carefully for information about new features, breaking changes,
and bugs fixed.  The latest full release notes can be viewed at:
  https://cloud.google.com/sdk/release_notes

318.0.0 (2020-11-10)

      . . .
      (release notes)
      . . .

    Subscribe to these release notes at
    https://groups.google.com/forum/#!forum/google-cloud-sdk-announce.

Do you want to continue (Y/n)?

╔════════════════════════════════════════════════════════════╗
╠═ Creating update staging area                             ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Uninstalling: Cloud SDK Core Libraries                   ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Uninstalling: gcloud cli dependencies                    ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Installing: Cloud SDK Core Libraries                     ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Installing: gcloud cli dependencies                      ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Creating backup and activating new installation          ═╣
╚════════════════════════════════════════════════════════════╝

Performing post processing steps...done.

Update done!

To revert your SDK to the previously installed version, you may run:
  $ gcloud components update --version 317.0.0

Затем используйте gcloud auth login для аутентификации для команд gcloud , которые вы будете выполнять в дальнейшем:

$ gcloud auth login
Your browser has been opened to visit:

    https://accounts.google.com/o/oauth2/auth?response_type=code&client_id= . . .

You are now logged in as [YOUR_EMAIL].
Your current project is [PROJECT_ID].  You can change this setting by running:
  $ gcloud config set project PROJECT_ID

Используйте gcloud config list , чтобы увидеть текущие настройки вашего проекта:

$ gcloud config list
[core]
account = YOUR_EMAIL
disable_usage_reporting = False
project = PROJECT_ID

Your active configuration is: [default]

Приведенная выше команда поможет вам создать новый проект или выбрать существующий. Если выходные данные gcloud config list не соответствуют выбранному проекту, который вы собираетесь использовать для этого руководства, запустите gcloud config set project PROJECT_ID чтобы установить идентификатор проекта. Затем убедитесь, что установлен правильный идентификатор проекта, снова запустив gcloud config list .

$ gcloud config set project PROJECT_ID
Updated property [core/project].

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

информационная карточка проекта

Последняя команда (#5), gcloud app deploy , предназначена для развертывания вашего приложения в App Engine. Поскольку мы только начинаем, запускать его сейчас необязательно, но мы, конечно, не препятствуем развертыванию кода Модуля 0, чтобы убедиться, что он работает. После выполнения выберите географический регион, в котором вы хотите, чтобы приложение работало (обычно там, где вы находитесь). Однако его нельзя изменить после установки. Затем просмотрите остальную информацию о развертывании. По завершении вы получите уведомление об URL-адресе, по которому будет обслуживаться ваше приложение. Вот сокращенная версия того, что вы можете увидеть:

$ gcloud app deploy
Services to deploy:

descriptor:      [/private/tmp/mod0-baseline/app.yaml]
source:          [/private/tmp/mod0-baseline]
target project:  [PROJECT_ID]
target service:  [default]
target version:  [20201116t220827]
target url:      [https://PROJECT_ID.REG_ABBR.r.appspot.com]


Do you want to continue (Y/n)?

Beginning deployment of service [default]...
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 1 file to Google Cloud Storage                 ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [default]...done.
Setting traffic split for service [default]...done.
Deployed service [default] to [https://PROJECT_ID.REG_ABBR.r.appspot.com]

You can stream logs from the command line by running:
  $ gcloud app logs tail -s default

To view your application in the web browser run:
  $ gcloud app browse

Если вы давно не использовали App Engine, вы можете заметить, что исходная команда appcfg.py update была заменена командой gcloud app deploy . Чтобы узнать больше о gcloud app deploy , посетите его страницу документации .

Еще одним недавним изменением является URL-адрес развернутых приложений: он изменен с http://PROJECT_ID.appspot.com на http://PROJECT_ID.REG_ABBR.r.appspot.com . Большинство приложений со временем будут преобразованы в новый формат. Подробнее о формате URL в документации по запросам и маршрутизации .

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

приложение Visitme

Если ваше приложение новое, вы увидите только одно или несколько посещений.

4. Добавьте стороннюю библиотеку Flask.

Среда выполнения Python 2 App Engine предоставляет набор «встроенных» сторонних библиотек, все что вам нужно сделать — это указать их в файле app.yaml для использования. Хотя эта миграция не требует их использования, они будут в следующем руководстве по миграции (для Модуля 2).

Сторонние библиотеки, которые не являются встроенными, необходимо указать в файле с именем requirements.txt и установить локально в папке lib в том же каталоге, что и код приложения, куда все загружается в App Engine. Дополнительную информацию можно найти в документации по объединению сторонних библиотек .

Скопированные библиотеки, такие как Flask, требуют, чтобы вы указали App Engine, чтобы они искали их в папке lib с помощью файла конфигурации appengine_config.py . Файл конфигурации appengine_config.py размещается в той же папке приложения верхнего уровня, что и requirements.txt и lib . В этой части урока вы:

  • Создайте requirements.txt (укажите скопированные [невстроенные] сторонние библиотеки)
  • Создайте appengine_config.py (распознавание сторонних библиотек)
  • Установите (сторонние) пакеты и зависимости

1. Создайте requirements.txt

Создайте файл requirements.txt , чтобы указать свои пакеты. В нашем случае Flask — это необходимая сторонняя библиотека. На момент написания этой статьи последней версией была 1.1.2, поэтому создайте requirements.txt включив в него одну строку:

Flask==1.1.2

Обратитесь к документации requirements.txt , чтобы узнать больше о поддерживаемых форматах.

2. Создайте appengine_config.py

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

from google.appengine.ext import vendor

# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)

Этот код делает именно то, что мы указали ранее, а именно указывает App Engine на папку lib для скопированных библиотек.

3. Установите пакет(ы) и зависимости.

Теперь запустите команду pip install , чтобы создать папку lib и установить туда Flask и его зависимости:

$ pip install -t lib -r requirements.txt

Независимо от того, использовали ли вы pip или pip2 , после завершения установки пакета у вас должна быть папка lib , содержимое которой будет похоже на:

$ ls lib
bin/
click/
click-7.1.2.dist-info/
flask/
Flask-1.1.2.dist-info/
itsdangerous/
itsdangerous-1.1.0.dist-info/
jinja2/
Jinja2-2.11.2.dist-info/
markupsafe/
MarkupSafe-1.1.1.dist-info/
werkzeug/
Werkzeug-1.0.1.dist-info/

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

Теперь давайте обновим файл приложения main.py

1. Импорт

Импорт идет первым, как и во всех файлах Python. За импортом платформы webapp2 следует библиотека Datastore ndb и, наконец, расширение App Engine, которое обрабатывает шаблоны с поддержкой Django. Вы должны увидеть следующее:

  • ДО:
import webapp2
from google.appengine.ext import ndb
from google.appengine.ext.webapp import template

При переходе на Flask вы одновременно импортируете как Flask, так и части средства рендеринга шаблона. Удалите пару импортов, связанных с webapp2 и замените их следующим образом (оставьте импорт ndb как есть):

  • ПОСЛЕ:
from flask import Flask, render_template, request
from google.appengine.ext import ndb

2. Запуск

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

  • ДО:
app = webapp2.WSGIApplication([
    ('/', MainHandler),
], debug=True)

Имейте в виду, что app.yaml выполняет маршрутизацию более высокого уровня и может вызывать разные обработчики. Пример приложения достаточно прост, поэтому все маршруты передаются обработчику main.py

Flask не использует подобные таблицы маршрутизации, поэтому удалите эти строки в main.py Flask также требует инициализации, поэтому добавьте следующую строку вверху main.py сразу под импортом:

  • ПОСЛЕ:
app = Flask(__name__)

В Flask вы инициализируете фреймворк, а затем используете декораторы для определения маршрутов. Кроме того, маршруты связаны с функциями, а не с классами или методами.

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

3. Модель данных

Здесь нет никаких изменений. Datastore будет в центре внимания следующей лаборатории кода.

4. Обработчики

Приложение, независимо от того, какой фреймворк вы используете ( webapp2 или Flask), выполняет 3 вещи:

  1. Обработка корневого пути ( / ) GET-запросов
  2. Зарегистрируйте веб-страницу «посещение» (создайте/сохраните объект Visit )
  3. Отобразить 10 самых последних посещений (с помощью заранее определенного шаблона index.html ).

Платформа webapp2 использует модель выполнения на основе классов, в которой для каждого поддерживаемого метода HTTP создаются обработчики. В нашем простом случае у нас есть только GET , поэтому определен метод get() :

  • ДО:
class MainHandler(webapp2.RequestHandler):
    def get(self):
        store_visit(self.request.remote_addr, self.request.user_agent)
        visits = fetch_visits(10) or ()  # empty sequence if None
        tmpl = os.path.join(os.path.dirname(__file__), 'index.html')
        self.response.out.write(template.render(tmpl, {'visits': visits}))

Как упоминалось выше, Flask выполняет собственную маршрутизацию. Вместо класса-обработчика вы пишете функции и украшаете их маршрутом, по которому они должны быть вызваны. Пользователи могут указать методы HTTP, обрабатываемые при вызове декоратора, например @app.route('/app/', methods=['GET', 'POST']) . Поскольку по умолчанию используется только GET (и неявно HEAD ), его можно оставить.

При переходе на Flask замените класс MainHandler и его метод get() следующей функцией маршрутизации Flask:

  • ПОСЛЕ:
@app.route('/')
def root():
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10) or ()  # empty sequence if None
    return render_template('index.html', visits=visits)

Конечно, это не является репрезентативным для вашего приложения, которое, безусловно, будет более сложным, чем этот образец. Одна из основных целей этих руководств — помочь вам начать работу, нарастить «мышечную память» и понять, где вносить изменения в код, специфичный для App Engine. Чтобы убедиться, что вы внесли это изменение правильно, сравните свое изменение с файлом main.py из Модуля 1 .

5. Вспомогательные файлы

В файле .gcloudignore нет никаких изменений. Его цель — указать файлы, которые не нужно развертывать в App Engine, которые не нужны для развертывания и выполнения приложения, включая, помимо прочего, вспомогательные файлы Python, систему управления версиями, шаблон репозитория и другие файлы. Наш .gcloudignore выглядит так (для краткости комментарии удалены):

.gcloudignore
.git
.gitignore
.hgignore
.hg/
*.pyc
*.pyo
__pycache__/
/setup.cfg
README.md

6. Обновите файл HTML-шаблона.

1. Переместить файл шаблона

В папке базового репозитория (модуль 0) файл шаблона index.html находится в той же папке, что и файлы приложения. Поскольку Flask требует, чтобы HTML-файлы находились в папке templates , вам необходимо создать эту папку ( mkdir templates ) и переместить туда index.html . В POSIX-совместимой системе, такой как Linux или Mac OS X, команды будут такими:

mkdir templates
mv index.html templates

2. Обновить файл шаблона.

После того как вы переместили index.html в templates , пришло время внести небольшие, но необходимые изменения. Давайте посмотрим на исходный файл шаблона целиком:

<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
<body>

<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
    <li>{{ visit.timestamp.ctime }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>

</body>
</html>

В то время как webapp2 использует шаблоны Django, которые выполняют вызовы, такие как visit.timestamp.ctime без круглых скобок ( ) , Jinja2 требует их явно. Хотя это звучит как незначительная настройка, шаблоны Jinja являются более мощными «из коробки», поскольку вы можете передавать аргументы в вызовах.

В Django вам нужно либо создать «тег шаблона», либо написать фильтр. Учитывая это, обновите index.html , добавив пару круглых скобок к вызову visit.timestamp.ctime :

  • ДО:
<li>{{ visit.timestamp.ctime }} from {{ visit.visitor }}</li>
  • ПОСЛЕ:
<li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>

Это единственное необходимое изменение; никаких дополнительных изменений в index.html для всех остальных кодовых лабораторий миграции не требуется.

7. Подведение итогов/очистка

Развернуть приложение

Когда вы внесете все изменения в этом руководстве, файлы в папке вашего приложения должны быть идентичны (или почти идентичны) файлу в папке репозитория Модуля 1 . Теперь разверните и убедитесь, что ваше приложение Flask модуля 1 работает идентично версии webapp2 модуля 0.

Используйте команду gcloud app deploy , как мы делали ранее при развертывании исходного кода Модуля 0. Доступ к приложению по адресу PROJECT_ID.appspot.com через веб-браузер или команду curl или wget , чтобы убедиться, что оно работает должным образом.

Если вы получаете какую-то ошибку сервера, это обычно означает какую-то опечатку в вашем коде Python. Просмотрите журналы приложений для расследования. Также сравните ваши файлы с файлами в репозитории Модуля 1 (ссылка чуть выше).

Дополнительно: очистка

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

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

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

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

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

Существует два модуля миграции, которые НАЧИНАЮТСЯ с завершенного кода Модуля 1, Модулей 2 и 7:

  • Модуль 2 (требуется, если вы используете хранилище данных)
    • Миграция с App Engine ndb на Cloud NDB
    • После перехода на Cloud NDB становится доступно множество других опций.
      • Контейнеризация вашего приложения для запуска в Cloud Run
      • Дальнейший перенос вашего приложения в клиентскую библиотеку Cloud Datastore.
      • Перенос вашего приложения в Cloud Firestore для доступа к функциям Firebase.
  • Модуль 7 (требуется, если вы используете очереди задач [push])
    • Добавление использования taskqueue App Engine (push)
    • Подготавливает приложение Модуля 1 к миграции в облачные задачи Модуля 8.

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

Проблемы и отзывы о модулях миграции App Engine

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

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

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

Кодлаб

Питон 2

Питон 3

Модуль 0

код

(н/д)

Модуль 1

код

(н/д)

Ресурсы App Engine

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