Миграция с Memcache App Engine на Cloud Memorystore (модуль 13)

1. Обзор

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

Цель этого практического занятия — показать разработчикам приложений на Python 2, как перейти с App Engine Memcache на Cloud Memorystore (для Redis ). Также предусмотрена неявная миграция с App Engine ndb на Cloud NDB , но она в основном рассматривается в практическом занятии модуля 2 ; для получения более подробной пошаговой информации ознакомьтесь с ним.

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

  • Настройте экземпляр Cloud Memorystore (через Cloud Console или инструмент gcloud ).
  • Настройте коннектор доступа к VPC-серверу Cloud Serverless (через Cloud Console или инструмент gcloud ).
  • Переход с App Engine Memcache на Cloud Memorystore
  • Реализуйте кэширование с помощью Cloud Memorystore в тестовом приложении.
  • Переход с App Engine ndb на Cloud NDB

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

Опрос

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

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

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

Новичок Средний Профессионал

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

Новичок Средний Профессионал

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

В этом практическом занятии показано, как перенести пример приложения с App Engine Memcache (и NDB) на Cloud Memorystore (и Cloud NDB). Этот процесс включает в себя замену зависимостей от встроенных сервисов App Engine, что делает ваши приложения более портативными. Вы можете либо остаться на App Engine, либо рассмотреть возможность перехода на любой из альтернативных вариантов, описанных ранее.

Эта миграция требует больше усилий по сравнению с другими в этой серии. Рекомендуемой заменой App Engine Memcache является Cloud Memorystore — полностью управляемый облачный сервис кэширования. Memorystore поддерживает пару популярных механизмов кэширования с открытым исходным кодом: Redis и Memcached . В этом модуле миграции используется Cloud Memorystore для Redis . Подробнее можно узнать в обзоре Memorystore и Redis .

Поскольку Memorystore требует работающего сервера, необходима также Cloud VPC . В частности, необходимо создать коннектор Serverless VPC Access , чтобы приложение App Engine могло подключаться к экземпляру Memorystore через его частный IP-адрес. После выполнения этой задачи вы обновите приложение таким образом, что, хотя оно будет работать как и раньше, Cloud Memorystore будет выступать в качестве службы кэширования, заменив службу Memcache в App Engine.

Этот учебный материал начинается с примера приложения из модуля 12 на Python 2, за которым следует дополнительное, необязательное, небольшое обновление до Python 3. Если вы уже знакомы с доступом к встроенным сервисам App Engine из Python 3 через SDK App Engine для Python 3 , вы можете начать с версии примера приложения из модуля 12 на Python 3. В этом случае использование SDK будет исключено, поскольку Memorystore не является встроенным сервисом App Engine. Изучение использования SDK App Engine для Python 3 выходит за рамки этого учебного материала.

В этом руководстве описаны следующие ключевые шаги:

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

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

Подготовка облачного проекта

Мы рекомендуем использовать тот же проект, что и для выполнения практического задания модуля 12. В качестве альтернативы вы можете создать совершенно новый проект или использовать уже существующий. Каждое практическое задание в этой серии имеет этап «СТАРТ» (базовый код, с которого следует начать) и этап «ФИНИШ» (мигрированное приложение). Код на этапе ФИНИШ предоставлен для того, чтобы вы могли сравнить свои решения с нашими в случае возникновения проблем. Вы всегда можете вернуться к этапу СТАРТ, если что-то пойдет не так. Эти контрольные точки предназначены для того, чтобы вы успешно освоили процесс миграции.

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

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

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

В папке START должны находиться следующие файлы:

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

Если вы начинаете с версии Python 2, то там также будет файл appengine_config.py и, возможно, папка lib , если вы выполнили практическое задание модуля 12.

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

Оставшиеся этапы подготовки:

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

Пользователям Python 2 следует удалить и переустановить папку lib с помощью следующих команд:

rm -rf ./lib; pip install -t lib -r requirements.txt                

Теперь всем пользователям Python 2 и 3 следует загрузить код в App Engine с помощью этой команды:

gcloud app deploy                

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

dfe56a02ae59ddd8.png

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

4. Настройте службы кэширования.

Cloud Memorystore не является бессерверной системой. Требуется экземпляр; в данном случае — экземпляр с запущенным Redis. В отличие от Memcache, Memorystore — это автономный облачный продукт, и у него нет бесплатного уровня , поэтому перед началом работы обязательно ознакомьтесь с информацией о ценах на Redis в Memorystore . Чтобы минимизировать затраты, мы рекомендуем использовать минимальное количество ресурсов: базовый уровень обслуживания и 1 ГБ памяти.

Экземпляр Memorystore находится в другой сети, чем ваше приложение App Engine (экземпляры), поэтому необходимо создать коннектор доступа к Serverless VPC , чтобы App Engine мог получить доступ к ресурсам Memorystore. Чтобы минимизировать затраты на VPC, выберите тип экземпляра ( f1-micro ) и минимальное количество запрашиваемых экземпляров (мы рекомендуем минимум 2 , максимум 3 ). Также ознакомьтесь со страницей информации о ценах на VPC .

Мы повторяем эти рекомендации по снижению затрат, попутно помогая вам создать каждый необходимый ресурс. Кроме того, при создании ресурсов Memorystore и VPC в Cloud Console в правом верхнем углу вы увидите калькулятор цен для каждого продукта, предоставляющий приблизительную оценку ежемесячных затрат (см. иллюстрацию ниже). Эти значения автоматически корректируются при изменении параметров. Примерно так вы и должны выглядеть:

7eb35ebf7248c010.png

Оба ресурса необходимы, и не имеет значения, какой из них вы создадите первым. Если вы сначала создадите экземпляр Memorystore, ваше приложение App Engine не сможет связаться с ним без коннектора VPC. Аналогично, если вы сначала создадите коннектор VPC, в этой сети VPC не будет ничего, с чем могло бы взаимодействовать ваше приложение App Engine. В этом руководстве вы сначала создадите экземпляр Memorystore, а затем коннектор VPC.

После того, как оба ресурса будут подключены, вам нужно будет добавить соответствующую информацию в app.yaml , чтобы ваше приложение могло получить доступ к кэшу. Вы также можете обратиться к руководствам по Python 2 или Python 3 в официальной документации. Также стоит ознакомиться с руководством по кэшированию данных на странице миграции Cloud NDB ( для Python 2 или Python 3 ).

Создайте экземпляр Cloud Memorystore.

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

  • Выберите самый низкий уровень обслуживания: Базовый (по умолчанию в консоли: "Стандартный", по умолчанию в gcloud : "Базовый").
  • Выберите минимальный объем хранилища: 1 ГБ (по умолчанию в консоли: 16 ГБ, по умолчанию gcloud : 1 ГБ).
  • Как правило, самые новые версии любого программного обеспечения требуют наибольшего количества ресурсов, но выбирать самую старую версию тоже, вероятно, не рекомендуется. Вторая по новизне версия на данный момент — Redis версии 5.0 (по умолчанию в консоли: 6.x).

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

Из облачной консоли

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

68318997e3105db6.png

После включения этой функции (и, возможно, одновременно с настройкой оплаты) вы попадете на панель управления Memorystore. Здесь вы можете увидеть все экземпляры, созданные в вашем проекте. В проекте, показанном ниже, их нет, поэтому вы видите сообщение «Нет строк для отображения». Чтобы создать экземпляр Memorystore, нажмите «Создать экземпляр » вверху:

63547aa575838a36.png

На этой странице представлена ​​форма, которую необходимо заполнить, указав желаемые настройки для создания экземпляра Memorystore:

b77d927287fdf4c7.png

Чтобы снизить затраты на этот учебный материал и его пример приложения, следуйте рекомендациям, изложенным ранее. После выбора параметров нажмите «Создать» . Процесс создания займет несколько минут. После его завершения скопируйте IP-адрес и номер порта экземпляра, чтобы добавить их в app.yaml .

Из командной строки

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

Как и в случае с Cloud Console, необходимо включить Cloud Memorystore для Redis. Выполните команду gcloud services enable redis.googleapis.com и дождитесь ее завершения, как в этом примере:

$ gcloud services enable redis.googleapis.com
Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.

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

gcloud redis instances create NAME --redis-version VERSION \
    --region REGION --project PROJECT_ID

Выберите имя для вашего экземпляра Memorystore; в этой лабораторной работе используется имя " demo-ms " вместе с идентификатором проекта " my-project ". Регион этого примера приложения — us-central1 (тот же, что и us-central ), но вы можете использовать регион, более близкий к вашему, если задержка имеет значение. Вы должны выбрать тот же регион, что и ваше приложение App Engine. Вы можете выбрать любую версию Redis по своему усмотрению, но мы используем версию 5, как было рекомендовано ранее. С учетом этих настроек, вот команда, которую вы должны выполнить (вместе с соответствующим выводом):

$ gcloud redis instances create demo-ms --region us-central1 \
    --redis-version redis_5_0 --project my-project

Create request issued for: [demo-ms]
Waiting for operation [projects/my-project/locations/us-central1/operations/operation-xxxx] to complete...done.
Created instance [demo-ms].

В отличие от настроек Cloud Console по умолчанию, gcloud по умолчанию использует минимальные ресурсы. В результате в этой команде не требуется указывать ни уровень обслуживания, ни объем хранилища. Создание экземпляра Memorystore занимает несколько минут, и после завершения запишите IP-адрес и номер порта экземпляра, так как они вскоре будут добавлены в app.yaml .

Подтвердите создание экземпляра.

Из облачной консоли или командной строки

Независимо от того, создали ли вы свой экземпляр через Cloud Console или командную строку, вы можете убедиться в его доступности и готовности к использованию с помощью этой команды: gcloud redis instances list --region REGION

Вот команда для проверки экземпляров в регионе us-central1 , а также ожидаемый результат, показывающий только что созданный нами экземпляр:

$ gcloud redis instances list --region us-central1
INSTANCE_NAME  VERSION    REGION       TIER   SIZE_GB  HOST         PORT  NETWORK  RESERVED_IP     STATUS  CREATE_TIME
demo-ms        REDIS_5_0  us-central1  BASIC  1        10.aa.bb.cc  6379  default  10.aa.bb.dd/29  READY   2022-01-28T09:24:45

При запросе информации об экземпляре или для настройки приложения обязательно используйте HOST и PORT (а не RESERVED_IP ). На панели мониторинга Cloud Memorystore в Cloud Console теперь должен отображаться этот экземпляр:

c5a6948ec1c056ed.png

Из виртуальной машины Compute Engine

Если у вас есть виртуальная машина Compute Engine, вы также можете отправлять прямые команды экземпляру Memorystore с виртуальной машины, чтобы подтвердить его работоспособность. Имейте в виду, что использование виртуальной машины может повлечь за собой дополнительные расходы, не зависящие от уже используемых вами ресурсов.

Создание коннектора доступа к VPC без серверной архитектуры

Как и в случае с Cloud Memorystore, вы можете создать бессерверный коннектор Cloud VPC в Cloud Console или в командной строке. Аналогично, у Cloud VPC нет бесплатного уровня , поэтому мы рекомендуем выделять минимальное количество ресурсов для выполнения практического задания, чтобы свести затраты к минимуму, чего можно достичь с помощью следующих настроек:

  • Выберите минимальное максимальное количество экземпляров: 3 (по умолчанию в консоли и gcloud : 10)
  • Выберите самый дешевый тип машины: f1-micro (по умолчанию в консоли: e2-micro , gcloud по умолчанию отсутствует)

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

Из облачной консоли

Перейдите на страницу «Доступ к VPC без сервера» в консоли Cloud Console (возможно, вам потребуется ввести платежную информацию). Если вы еще не включили API, вам будет предложено это сделать:

e3b9c0651de25e97.png

После включения API (и, возможно, одновременно с оплатой) вы попадете на панель управления, где будут отображаться все созданные коннекторы VPC. В проекте, показанном на скриншоте ниже, коннекторов нет, поэтому отображается сообщение «Нет строк для отображения». В консоли нажмите «Создать коннектор» вверху:

b74b49b9d73b7dcf.png

Заполните форму, указав желаемые настройки:

6b26b2aafa719f73.png

Выберите подходящие настройки для ваших приложений. Для этого руководства и его примера приложения с минимальными потребностями имеет смысл минимизировать затраты, поэтому следуйте рекомендациям, изложенным ранее. После выбора параметров нажмите «Создать» . Запрос на подключение VPC-коннектора займет несколько минут.

Из командной строки

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

$ gcloud services enable vpcaccess.googleapis.com
Operation "operations/acf.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.

При включенном API создается коннектор VPC с помощью команды, которая выглядит следующим образом:

gcloud compute networks vpc-access connectors create CONNECTOR_NAME \
    --range 10.8.0.0/28 --region REGION --project PROJECT_ID

Выберите имя для вашего коннектора, а также неиспользуемый IP-адрес, начинающийся с блока CIDR /28 . В этом руководстве предполагаются следующие условия:

  • Идентификатор проекта : my-project
  • Имя коннектора VPC : demo-vpc
  • Минимальное количество экземпляров : 2 (по умолчанию), максимальное количество экземпляров : 3.
  • Тип экземпляра : f1-micro
  • Регион : us-central1
  • Блок IPv4 CIDR : 10.8.0.0/28 (как рекомендуется в облачной консоли)

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

$ gcloud compute networks vpc-access connectors create demo-vpc \
    --max-instances 3 --range 10.8.0.0/28 --machine-type f1-micro \
    --region us-central1  --project my-project

Create request issued for: [demo-vpc]
Waiting for operation [projects/my-project/locations/us-central1/operations/xxx] to complete...done.
Created connector [demo-vpc].

Приведённая выше команда не указывает значения по умолчанию, такие как минимальное количество экземпляров, равное 2, и сеть с именем default . Создание коннектора VPC занимает несколько минут.

Подтвердите создание коннектора.

После завершения процесса выполните следующую команду gcloud , предполагая, что используется регион us-central1 , чтобы подтвердить, что он создан и готов к использованию:

$ gcloud compute networks vpc-access connectors list --region us-central1
CONNECTOR_ID  REGION       NETWORK  IP_CIDR_RANGE  SUBNET  SUBNET_PROJECT  MIN_THROUGHPUT  MAX_THROUGHPUT  STATE
demo-vpc      us-central1  default  10.8.0.0/28                            200             300             READY

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

e03db2c8140ed014.png

Обратите внимание на идентификатор облачного проекта, имя коннектора VPC и регион.

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

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

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

requirements.txt

В этом разделе мы добавляем пакеты для поддержки Cloud Memorystore, а также Cloud NDB. Для Cloud Memorystore для Redis достаточно использовать стандартный клиент Redis для Python ( redis ), поскольку отдельной библиотеки для работы с Cloud Memorystore не существует. Добавьте redis и google-cloud-ndb в requirements.txt , добавив flask из модуля 12:

flask
redis
google-cloud-ndb

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

app.yaml

Добавить новые разделы

Для работы среды выполнения Python 2 App Engine при использовании облачных API, таких как Cloud NDB, требуются определенные сторонние пакеты, а именно grpcio и setuptools . Пользователям Python 2 необходимо указать в файле app.yaml список встроенных библиотек, а также их доступную версию . Если у вас еще нет раздела libraries , создайте его и добавьте обе библиотеки следующим образом:

libraries:
- name: grpcio
  version: latest
- name: setuptools
  version: latest

При миграции вашего приложения раздел libraries может уже присутствовать. Если это так, и отсутствуют grpcio и setuptools , просто добавьте их в существующий раздел libraries .

Далее, нашему тестовому приложению необходима информация об экземпляре Cloud Memorystore и коннекторе VPC, поэтому добавьте следующие два новых раздела в app.yaml независимо от того, какую среду выполнения Python вы используете:

env_variables:
    REDIS_HOST: 'YOUR_REDIS_HOST'
    REDIS_PORT: 'YOUR_REDIS_PORT'

vpc_access_connector:
    name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR

На этом необходимые обновления заканчиваются. Обновленный файл 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

env_variables:
    REDIS_HOST: 'YOUR_REDIS_HOST'
    REDIS_PORT: 'YOUR_REDIS_PORT'

vpc_access_connector:
    name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR

Ниже приведено сравнение «до» и «после», иллюстрирующее изменения, которые следует внести в app.yaml :

ec2bb027a67debb6.png

*Отличия Python 3

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

Ни threadsafe , ни api_version не используются в среде выполнения Python 3, поэтому удалите оба этих параметра. Последняя версия среды выполнения App Engine не поддерживает встроенные сторонние библиотеки , а также копирование библиотек, не являющихся встроенными . Единственное требование для сторонних пакетов — указать их в requirements.txt . В результате весь раздел libraries в app.yaml можно удалить.

Далее, среда выполнения Python 3 требует использования веб-фреймворков, которые выполняют собственную маршрутизацию, поэтому в Модуле 1 мы показали разработчикам, как перейти с webp2 на Flask . В результате все обработчики скриптов должны быть изменены на auto . Поскольку это приложение не обслуживает статические файлы, перечисление обработчиков "бессмысленно" (так как все они auto ), поэтому весь раздел handlers также можно удалить. В результате ваш новый, сокращенный app.yaml , адаптированный для Python 3, должен выглядеть следующим образом:

runtime: python39

env_variables:
    REDIS_HOST: 'YOUR_REDIS_HOST'
    REDIS_PORT: 'YOUR_REDIS_PORT'

vpc_access_connector:
    name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR

Подводя итог различиям в app.yaml при переносе на Python 3:

  • Удалите настройки threadsafe и api_version
  • Удалить раздел libraries
  • Удалите раздел handlers (или только обработчики script если ваше приложение обслуживает статические файлы).

Замените значения

Значения в новых разделах для Memorystore и коннектора VPC являются лишь заполнителями. Замените эти значения, написанные заглавными буквами ( YOUR_REDIS_HOST, YOUR_REDIS_PORT, PROJECT_ID, REGION, CONNECTOR_NAME ), значениями, сохраненными при создании этих ресурсов ранее. Что касается вашего экземпляра Memorystore, обязательно используйте HOST (а не RESERVED_IP ) и PORT . Вот быстрый способ получить HOST и PORT из командной строки, предполагая, что имя экземпляра — demo-ms , а REGIONus-central1 :

$ gcloud redis instances describe demo-ms --region us-central1 \
    --format "value(host,port)"
10.251.161.51   6379

Если в нашем примере IP-адрес экземпляра Redis — 10.10.10.10 , используется порт 6379 проект my-project расположен в регионе us-central1 , а имя коннектора VPC — demo-vpc , то разделы в app.yaml будут выглядеть следующим образом:

env_variables:
    REDIS_HOST: '10.10.10.10'
    REDIS_PORT: '6379'

vpc_access_connector:
    name: projects/my-project/locations/us-central1/connectors/demo-vpc

Создайте или обновите файл appengine_config.py.

Добавлена ​​поддержка встроенных сторонних библиотек.

Как и в случае с app.yaml , добавьте использование библиотек grpcio и setuptools . Измените appengine_config.py для поддержки встроенных сторонних библиотек. Если это кажется вам знакомым, то это потому, что это также требовалось в Модуле 2 при миграции с App Engine ndb на Cloud NDB. Необходимое изменение — добавить папку lib в рабочий набор setuptools.pkg_resources :

4140b3800694f77e.png

*Отличия Python 3

Этот раздел необязателен и применяется только при портировании на Python 3. Одним из приятных изменений второго поколения App Engine является то, что копирование (иногда называемое «внедрением») сторонних пакетов (не встроенных) и ссылки на встроенные сторонние пакеты в app.yaml больше не требуются, а это значит, что вы можете удалить весь файл appengine_config.py .

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

Приложение состоит всего из одного файла — main.py , поэтому все изменения в этом разделе затрагивают только этот файл. Мы предоставили графическое представление изменений, которые мы собираемся внести для миграции этого приложения в Cloud Memorystore. Это лишь иллюстративный пример, не предназначенный для детального анализа. Вся основная работа заключается в изменениях, которые мы внесем в код.

5d043768ba7be742.png

Давайте разберемся с этими разделами по очереди, начиная сверху.

Обновить импорты

В разделе импорта main.py для модуля 12 используются Cloud NDB и Cloud Tasks; вот их импорты:

ДО:

from flask import Flask, render_template, request
from google.appengine.api import memcache
from google.appengine.ext import ndb

Для перехода на Memorystore требуется чтение переменных окружения, а это значит, что нам нужен модуль Python os , а также redis — клиент Redis для Python. Поскольку Redis не может кэшировать объекты Python, сериализуйте список последних посещений с помощью pickle , поэтому импортируйте его тоже. Одним из преимуществ Memcache является автоматическая сериализация объектов, тогда как Memorystore требует немного больше самостоятельного подхода. Наконец, обновите App Engine ndb до Cloud NDB, заменив google.appengine.ext.ndb на google.cloud.ndb . После этих изменений ваши импорты должны выглядеть следующим образом:

ПОСЛЕ:

import os
import pickle
from flask import Flask, render_template, request
from google.cloud import ndb
import redis

Обновление инициализации

Инициализация модуля 12 состоит в создании экземпляра объекта приложения Flask ` app и установке константы для кэширования в течение часа:

ДО :

app = Flask(__name__)
HOUR = 3600

Для использования облачных API требуется клиент, поэтому создайте экземпляр клиента Cloud NDB сразу после Flask. Затем получите IP-адрес и номер порта для экземпляра Memorystore из переменных окружения, которые вы установили в app.yaml . Вооружившись этой информацией, создайте экземпляр клиента Redis. Вот как выглядит ваш код после этих обновлений:

ПОСЛЕ:

app = Flask(__name__)
ds_client = ndb.Client()
HOUR = 3600
REDIS_HOST = os.environ.get('REDIS_HOST', 'localhost')
REDIS_PORT = os.environ.get('REDIS_PORT', '6379')
REDIS = redis.Redis(host=REDIS_HOST, port=REDIS_PORT)

*Миграция Python 3

Этот раздел необязателен, и если вы начинаете с версии приложения Module 12 на Python 3, то потребуется внести несколько изменений, касающихся импорта и инициализации.

Во-первых, поскольку Memcache является встроенной службой App Engine, для его использования в приложении Python 3 требуется SDK App Engine, а именно, оболочка для WSGI-приложения (а также другая необходимая конфигурация ):

ДО:

from flask import Flask, render_template, request
from google.appengine.api import memcache, wrap_wsgi_app
from google.appengine.ext import ndb

app = Flask(__name__)
app.wsgi_app = wrap_wsgi_app(app.wsgi_app)
HOUR = 3600

Поскольку мы переходим на Cloud Memorystore (а не на встроенный сервис App Engine, такой как Memcache), использование SDK необходимо удалить. Это несложно: достаточно удалить всю строку, которая импортирует memcache и wrap_wsgi_app . Также удалите строку, вызывающую wrap_wsgi_app() . После этих изменений эта часть приложения (фактически, всё приложение) останется идентичной версии на Python 2.

ПОСЛЕ:

import os
import pickle
from flask import Flask, render_template, request
from google.cloud import ndb
import redis

app = Flask(__name__)
ds_client = ndb.Client()
HOUR = 3600
REDIS_HOST = os.environ.get('REDIS_HOST', 'localhost')
REDIS_PORT = os.environ.get('REDIS_PORT', '6379')
REDIS = redis.Redis(host=REDIS_HOST, port=REDIS_PORT)

Наконец, удалите использование SDK из app.yaml (удалите строку: app_engine_apis: true ) и requirements.txt (удалите строку: appengine-python-standard ).

Переход на Cloud Memorystore (и Cloud NDB)

Модель данных Cloud NDB предназначена для совместимости с моделью данных App Engine ndb , а это значит, что определение объектов Visit остается неизменным. По аналогии с миграцией модуля 2 на Cloud NDB, все вызовы Datastore в store_visit() и fetch_visits() дополнены и встроены в новый блок with (поскольку требуется использование контекстного менеджера Cloud NDB). Вот эти вызовы до изменения:

ДО:

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 Visit.query().order(-Visit.timestamp).fetch(limit)

Добавьте блок ` with ds_client.context() в обе функции и поместите вызовы Datastore внутрь (с отступом). В этом случае никаких изменений в самих вызовах не требуется:

ПОСЛЕ:

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 Visit.query().order(-Visit.timestamp).fetch(limit)

Далее рассмотрим изменения в кэшировании. Вот функция main() из модуля 12:

ДО:

@app.route('/')
def root():
    'main application (GET) handler'
    # check for (hour-)cached visits
    ip_addr, usr_agt = request.remote_addr, request.user_agent
    visitor = '{}: {}'.format(ip_addr, usr_agt)
    visits = memcache.get('visits')

    # register visit & run DB query if cache empty or new visitor
    if not visits or visits[0].visitor != visitor:
        store_visit(ip_addr, usr_agt)
        visits = list(fetch_visits(10))
        memcache.set('visits', visits, HOUR)  # set() not add()

    return render_template('index.html', visits=visits)

В Redis есть вызовы `get` и `set`, как и в Memcache. Всё, что нам нужно сделать, это поменять местами соответствующие клиентские библиотеки, верно? Почти. Как упоминалось ранее, мы не можем кэшировать список Python с помощью Redis (потому что его нужно сначала сериализовать, что Memcache делает автоматически), поэтому в вызове set() нужно «сериализовать» посещения в строку с помощью pickle.dumps() . Аналогично, при извлечении посещений из кэша необходимо десериализовать их с помощью pickle.loads() сразу после ` get() . Вот основной обработчик после внесения этих изменений:

ПОСЛЕ:

@app.route('/')
def root():
    'main application (GET) handler'
    # check for (hour-)cached visits
    ip_addr, usr_agt = request.remote_addr, request.user_agent
    visitor = '{}: {}'.format(ip_addr, usr_agt)
    rsp = REDIS.get('visits')
    visits = pickle.loads(rsp) if rsp else None

    # register visit & run DB query if cache empty or new visitor
    if not visits or visits[0].visitor != visitor:
        store_visit(ip_addr, usr_agt)
        visits = list(fetch_visits(10))
        REDIS.set('visits', pickle.dumps(visits), ex=HOUR)

    return render_template('index.html', visits=visits)

На этом завершаются изменения, необходимые в main.py для преобразования использования Memcache в примере приложения в Cloud Memorystore. А что насчет HTML-шаблона и переноса на Python 3?

Обновить HTML-шаблон и перенести на Python 3?

Сюрприз! Здесь ничего делать не нужно, поскольку приложение разработано для работы как на Python 2, так и на Python 3 без каких-либо изменений кода или библиотек совместимости. Вы обнаружите, main.py идентичен в папках "FINISH" mod13a (2.x) и mod13b (3.x). То же самое относится и к файлу requirements.txt , за исключением различий в номерах версий (если они используются). Поскольку пользовательский интерфейс остается неизменным, обновления файла templates/index.html также отсутствуют.

Все необходимое для запуска этого приложения на Python 3 App Engine было выполнено ранее в конфигурации: из app.yaml были удалены ненужные директивы, а файлы appengine_config.py и папка lib были удалены, поскольку они не используются в Python 3.

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

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

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

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

rm -rf ./lib
pip install -t lib -r requirements.txt

Разработчикам, использующим Python 2 и 3, теперь следует развертывать свои приложения с помощью следующей команды:

gcloud app deploy

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

Модуль 7, приложение visitme

На этом этапе завершается практическое занятие. Мы предлагаем вам сравнить ваше обновленное тестовое приложение с одним из папок модуля 13: mod13a (Python 2) или mod13b (Python 3).

Уборка

Общий

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

Для полной ясности, развертывание на бессерверной вычислительной платформе 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 *, например, " us ", если ваше приложение размещено в США.

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

Это относится именно к данному практическому занятию.

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

  • Для работы Cloud Memorystore требуются экземпляры, и у него нет бесплатного тарифа; чтобы узнать больше о стоимости использования, см. страницу с ценами .
  • Для работы коннекторов Cloud Serverless VPC Access требуются экземпляры, и для них нет бесплатного тарифа; чтобы узнать больше о стоимости использования, см. соответствующий раздел на странице цен Cloud VPC .
  • Cloud Datastore (Cloud Firestore в режиме хранилища данных) предлагает бесплатный тариф; подробную информацию можно найти на странице с ценами .

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

  • App Engine
  • Облачное хранилище данных
  • Облачное хранилище памяти
  • Облачная VPC

Ниже приведены инструкции по предоставлению этих ресурсов и по предотвращению/минимизации расходов на их использование.

Остановите экземпляр Memorystore и коннектор VPC.

Это продукты без бесплатного уровня , поэтому с вас уже взимается плата. Если вы не завершите свой облачный проект (см. следующий раздел), вам необходимо удалить как экземпляр Memorystore, так и коннектор VPC, чтобы прекратить начисление платы. Аналогично созданию этих ресурсов, вы также можете освободить их либо из консоли Cloud, либо из командной строки.

Из облачной консоли

Чтобы удалить экземпляр Memorystore, вернитесь на панель управления Memorystore и щелкните по идентификатору экземпляра:

2b09baf1aa2e0a25.png

На странице с подробной информацией об этом экземпляре нажмите «Удалить» и подтвердите действие:

f9d9eb1c1d4c6107.png

Чтобы удалить коннектор VPC, перейдите на его панель управления, установите флажок рядом с коннектором, который хотите удалить, затем нажмите «Удалить» и подтвердите удаление.

ca5fbd9f4c7c9b60.png

Из командной строки

Следующие две команды gcloud удаляют, соответственно, экземпляр Memorystore и коннектор VPC:

  • gcloud redis instances delete INSTANCE --region REGION
  • gcloud compute networks vpc-access connectors delete CONNECTOR --region REGION

If you haven't set your project ID with gcloud config set project , you may have to provide --project PROJECT_ID . If your Memorystore instance is called demo-ms and VPC connector called demo-vpc , and both are in region us-central1 , issue the following pair of commands and confirm:

$ gcloud redis instances delete demo-ms --region us-central1
You are about to delete instance [demo-ms] in [us-central1].
Any associated data will be lost.

Do you want to continue (Y/n)?

Delete request issued for: [demo-ms]
Waiting for operation [projects/PROJECT/locations/REGION/operations/operation-aaaaa-bbbbb-ccccc-ddddd] to complete...done.
Deleted instance [demo-ms].
$
$ gcloud compute networks vpc-access connectors delete demo-vpc --region us-central1
You are about to delete connector [demo-vpc] in [us-central1].
Any associated data will be lost.

Do you want to continue (Y/n)?

Delete request issued for: [demo-vpc]
Waiting for operation [projects/PROJECT/locations/REGION/operations/aaaaa-bbbb-cccc-dddd-eeeee] to complete...done.
Deleted connector [demo-vpc].

Each request takes a few minutes to run. These steps are optional if you choose to shut down your entire Cloud project as described earlier, however you still incur billing until the shut down process has completed.

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

Beyond this tutorial, other migration modules that focus on moving away from the legacy bundled services to consider include:

  • Module 2 : migrate from App Engine ndb to Cloud NDB
  • Modules 7-9 : migrate from App Engine Task Queue push tasks to Cloud Tasks
  • Modules 12-13 : migrate from App Engine Memcache to Cloud Memorystore
  • Modules 15-16 : migrate from App Engine Blobstore to Cloud Storage
  • Modules 18-19 : migrate from App Engine Task Queue (pull tasks) to Cloud Pub/Sub

App Engine is no longer the only serverless platform in Google Cloud. If you have a small App Engine app or one that has limited functionality and wish to turn it into a standalone microservice, or you want to break-up a monolithic app into multiple reusable components, these are good reasons to consider moving to Cloud Functions . If containerization has become part of your application development workflow, particularly if it consists of a CI/CD (continuous integration/continuous delivery or deployment) pipeline, consider migrating to Cloud Run . These scenarios are covered by the following modules:

  • Migrate from App Engine to Cloud Functions: see Module 11
  • Migrate from App Engine to Cloud Run: see Module 4 to containerize your app with Docker, or Module 5 to do it without containers, Docker knowledge, or Dockerfile s

Switching to another serverless platform is optional, and we recommend considering the best options for your apps and use cases before making any changes.

Regardless of which migration module you consider next, all Serverless Migration Station content (codelabs, videos, source code [when available]) can be accessed at its open source repo . The repo's README also provides guidance on which migrations to consider and any relevant "order" of Migration Modules.

8. Additional resources

Listed below are additional resources for developers further exploring this or related Migration Module as well as related products. This includes places to provide feedback on this content, links to the code, and various pieces of documentation you may find useful.

Codelabs issues/feedback

If you find any issues with this codelab, please search for your issue first before filing. Links to search and create new issues:

Migration resources

Links to the repo folders for Module 12 (START) and Module 13 (FINISH) can be found in the table below. They can also be accessed from the repo for all App Engine codelab migrations which you can clone or download a ZIP file.

Кодлаб

Python 2

Python 3

Модуль 12

код

код

Module 13 (this codelab)

код

код

Online references

Below are online resources which may be relevant for this tutorial:

App Engine

App Engine NDB and Cloud NDB

App Engine Memcache and Cloud Memorystore

Cloud VPC

Other Cloud information

Лицензия

This work is licensed under a Creative Commons Attribution 2.0 Generic License.