1. Обзор
Эта серия практических занятий (самостоятельное обучение) призвана помочь разработчикам Google App Engine (Standard) модернизировать свои приложения, проведя их через ряд миграций. Наиболее важным шагом является отказ от встроенных сервисов оригинальной среды выполнения, поскольку среды выполнения следующего поколения более гибкие, предоставляя пользователям большее разнообразие вариантов сервисов. Переход на среду выполнения нового поколения позволяет проще интегрироваться с продуктами Google Cloud, использовать более широкий спектр поддерживаемых сервисов и поддерживать текущие версии языков программирования.
В этом вводном руководстве показаны первые шаги миграции для модернизации веб-фреймворка в приложениях App Engine: переход с webapp2 на Flask . В вашем приложении вы можете использовать любой веб-фреймворк, который обрабатывает маршрутизацию, но для этого руководства мы используем Flask, поскольку он широко используется сообществом.
Вы узнаете, как
- Используйте сторонние библиотеки (встроенные или собственные).
- Обновите конфигурационные файлы
- Перенос простого приложения с
webapp2на Flask.
Что вам понадобится
- Проект Google Cloud Platform, в котором участвуют:
- Базовые навыки работы с Python.
- Практические навыки работы с основными командами Linux.
- Базовые знания разработки и развертывания приложений на платформе App Engine.
Опрос
Как вы будете использовать этот практический урок?
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 не является желаемым фреймворком для переноса вашего приложения, вы можете выбрать другой, при условии, что он имеет собственную маршрутизацию. Этот практический пример демонстрирует руководителям ИТ-подразделений и разработчикам этапы миграции, чтобы вы могли ознакомиться с этим процессом независимо от того, на какой фреймворк вы в итоге перейдете.
Вот основные этапы этой миграции:
- Подготовка/Настройка
- Добавить стороннюю библиотеку Flask
- Обновите файлы приложения
- Обновите HTML-шаблон файла
3. Подготовка/Предварительные работы
Прежде чем приступить к основной части урока, давайте настроим наш проект, получим код, а затем (снова) ознакомим вас с командой gcloud и развернем базовое приложение, чтобы убедиться, что мы начали с работающего кода.
1. Настройка проекта
Если вы уже являетесь разработчиком, на панели управления App Engine, скорее всего, уже отображаются запущенные вами сервисы. Для целей этого руководства мы рекомендуем создать совершенно новый проект или использовать существующий. Убедитесь, что у проекта есть активный платежный аккаунт и приложение App Engine включено.
2. Загрузите базовый пример приложения.
В репозитории миграции GAE есть весь необходимый код. Клонируйте его или скачайте ZIP-файл. Для этого урока вы начнете с кода в папке Модуля 0 (START), и после завершения урока ваш код должен совпадать с кодом из папки Модуля 1 (FINISH). Если это не так, проверьте различия, чтобы перейти к следующей лабораторной работе.
- СТАРТ: Код модуля 0
- ЗАВЕРШЕНИЕ: Код модуля 1
- Весь репозиторий (для клонирования или загрузки ZIP-архива)
В папке Module 0 должны находиться файлы, которые выглядят следующим образом, как показано командой POSIX ls :
$ ls
app.yaml index.html main.py
3. (Повторно) ознакомьтесь с командами gcloud .
Если у вас еще нет команды gcloud на компьютере, установите Google Cloud SDK и убедитесь, что gcloud доступен в пути выполнения команд, а также ознакомьтесь со следующими командами gcloud :
-
gcloud components update— обновление Google Cloud SDK -
gcloud auth login— вход в вашу учетную запись с учетными данными -
gcloud config list— список настроек конфигурации проекта GCP -
gcloud config set project PROJECT_ID— установить идентификатор проекта GCP -
gcloud app deploy— разверните ваше приложение App Engine
Если вы в последнее время не занимались разработкой приложений с использованием gcloud на App Engine, вам следует выполнить первые четыре команды (#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].
Если вы предпочитаете использовать облачную консоль , вы можете создать новый проект, следуя инструкциям в пользовательском интерфейсе, или использовать любой уже существующий проект. На панели управления вашего проекта вы увидите карточку с информацией о проекте, где указан его идентификатор (а также название и номер проекта):

Последняя команда (#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-адресов содержится в документации по запросам и маршрутизации .
После развертывания приложения обновите страницу в браузере (возможно, несколько раз), чтобы увидеть последние посещения:

Если ваше приложение новое, вы увидите только одно или несколько посещений.
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 следует библиотека ndb Datastore, и, наконец, расширение 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 задачи:
- Обработка GET-запросов к корневому пути (
/). - Зарегистрируйте «посещение» веб-страницы (создайте/сохраните объект
Visit). - Отобразить 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 (ссылка чуть выше).
Необязательно: Уборка
Как насчет того, чтобы навести порядок и избежать выставления счетов до тех пор, пока вы не будете готовы перейти к следующему этапу миграции на CodeLab? Как опытные разработчики, вы, вероятно, уже знакомы с информацией о ценах App Engine .
(Необязательно): Отключить приложение
Если вы ещё не готовы перейти к следующему уроку, отключите своё приложение, чтобы избежать списания средств. Когда вы будете готовы перейти к следующему практическому занятию, вы можете снова включить его. Пока ваше приложение отключено, оно не будет получать трафик, за который могли бы взиматься плата, однако с вас могут взиматься дополнительные платежи за использование хранилища данных , если оно превысит бесплатную квоту , поэтому удалите достаточно данных, чтобы уложиться в этот лимит.
С другой стороны, если вы не собираетесь продолжать миграции и хотите полностью удалить все, вы можете закрыть свой проект .
Следующие шаги
Существует два модуля миграции, которые НАЧИНАЮТСЯ с завершенного кода Модуля 1, а именно Модулей 2 и 7:
- Модуль 2 (необходим, если вы используете Datastore)
- Переход с App Engine
ndbна Cloud NDB - После перехода на Cloud NDB становится доступно множество других вариантов.
- Контейнеризация вашего приложения для запуска в Cloud Run
- Дальнейшая миграция вашего приложения в клиентскую библиотеку Cloud Datastore.
- Перенос вашего приложения в Cloud Firestore для доступа к функциям Firebase.
- Переход с App Engine
- Модуль 7 (необходим, если вы используете очереди задач [push])
- Добавить использование
taskqueueApp Engine (push). - Подготовка приложения из Модуля 1 к миграции в облако. Задачи из Модуля 8.
- Добавить использование
8. Дополнительные ресурсы
Проблемы/обратная связь по модулю миграции App Engine на Codelabs
Если вы обнаружите какие-либо проблемы в этом практическом задании, пожалуйста, сначала найдите свою проблему, прежде чем сообщать о ней. Ссылки для поиска и создания новых проблем:
Миграционные ресурсы
Ссылки на папки репозитория для Модуля 0 (НАЧАЛО) и Модуля 1 (ЗАВЕРШЕНИЕ) можно найти в таблице ниже. Доступ к ним также можно получить из репозитория для всех миграций App Engine , который можно клонировать или загрузить в виде ZIP-файла.
Кодлаб | Python 2 | Python 3 |
Модуль 0 | (н/д) | |
Модуль 1 | (н/д) |
Ресурсы App Engine
Ниже приведены дополнительные ресурсы, касающиеся данной конкретной миграции:
- Микровеб-фреймворки на Python
- (СТАРОЕ) Переход с Python 2.5 на 2.7 и
webappнаwebapp2 - Переход на Python 3 и среду выполнения GAE нового поколения
- Общий