Миграция задач извлечения из очереди задач App Engine в Cloud Pub/Sub (модуль 19)

1. Обзор

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

Цель этой лаборатории кода — показать разработчикам App Engine Python 2, как перейти от задач извлечения из очереди задач App Engine в Cloud Pub/Sub . Также предусмотрен неявный переход с App Engine NDB на Cloud NDB для доступа к хранилищу данных (в основном описанный в модуле 2), а также обновление до Python 3.

В модуле 18 вы узнаете, как добавить в свое приложение использование задач извлечения . В этом модуле вы возьмете готовое приложение Модуля 18 и перенесете его использование в Cloud Pub/Sub. Те, кто использует очереди задач для push -задач, вместо этого перейдут на облачные задачи и вместо этого должны обратиться к модулям 7–9.

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

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

Опрос

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

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

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

Новичок Средний Опытный

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

Новичок Средний Опытный

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

Очередь задач App Engine поддерживает задачи как push, так и pull. Чтобы улучшить переносимость приложений, Google Cloud рекомендует перейти с устаревших комплексных служб, таких как очередь задач, на другие автономные облачные или сторонние эквивалентные службы.

Модули миграции 7–9 посвящены миграции задач принудительной передачи, а Модули 18–19 посвящены миграции задач по запросу. Хотя облачные задачи более точно соответствуют задачам push-уведомлений из очереди задач, Pub/Sub не так близок к задачам извлечения из очереди задач.

Pub/Sub имеет больше возможностей, чем функция извлечения, предоставляемая очередью задач. Например, Pub/Sub также имеет функцию принудительной отправки , однако облачные задачи больше похожи на задачи принудительной отправки из очереди задач, поэтому push-отправка Pub/Sub не покрывается ни одним из модулей миграции. В этой лаборатории кода Модуля 19 показано переключение механизма организации очередей с очередей извлечения очереди задач на Pub/Sub, а также миграция с App Engine NDB на Cloud NDB для доступа к хранилищу данных, повторяя миграцию Модуля 2 .

Хотя код Модуля 18 «рекламируется» как пример приложения Python 2, сам исходный код совместим с Python 2 и 3, и он остается таким даже после перехода на Cloud Pub/Sub (и Cloud NDB) здесь, в Модуле 19.

Это руководство включает в себя следующие шаги:

  1. Настройка/Предварительная работа
  2. Обновить конфигурацию
  3. Изменить код приложения

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

В этом разделе объясняется, как:

  1. Настройте свой облачный проект
  2. Получить базовый образец приложения
  3. (Повторное)развертывание и проверка базового приложения.
  4. Включите новые сервисы/API Google Cloud

Эти шаги гарантируют, что вы начнете с рабочего кода и будете готовы к миграции в облачные службы.

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

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

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

Одним из обязательных условий является работающее приложение App Engine Модуля 18, поэтому либо заполните его кодовую лабораторию (рекомендуется; ссылка выше), либо скопируйте код Модуля 18 из репозитория. Независимо от того, используете ли вы свой или наш, мы начнем именно с этого («СТАРТ»). Эта лаборатория кода проведет вас через миграцию, завершающуюся кодом, похожим на тот, что находится в папке репозитория Модуля 19 («FINISH»).

Независимо от того, какое приложение Модуля 18 вы используете, папка должна выглядеть так, как показано ниже, возможно, с папкой lib :

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

3. (Повторное) развертывание и проверка базового приложения.

Выполните следующие шаги, чтобы развернуть приложение Модуля 18:

  1. Удалите папку lib , если она есть, и запустите pip install -t lib -r requirements.txt чтобы повторно заполнить lib . Вместо этого вам может потребоваться использовать pip2 если на вашей машине разработки установлены Python 2 и 3.
  2. Убедитесь, что вы установили и инициализировали инструмент командной строки gcloud и проверили его использование .
  3. (Необязательно) Настройте свой облачный проект с помощью gcloud config set project PROJECT_ID если вы не хотите вводить PROJECT_ID с каждой командой gcloud , которую вы вводите.
  4. Разверните пример приложения с помощью gcloud app deploy
  5. Убедитесь, что приложение работает как положено и без проблем. Если вы выполнили лабораторную работу по Модулю 18, приложение отображает самых популярных посетителей, а также самые последние посещения (показано ниже). В противном случае количество посетителей может отсутствовать.

b667551dcbab1a09.png

Прежде чем переносить пример приложения из Модуля 18, необходимо сначала включить облачные службы, которые будет использовать измененное приложение.

4. Включите новые сервисы/API Google Cloud.

В старом приложении использовались встроенные службы App Engine, которые не требуют дополнительной настройки, в отличие от автономных облачных служб, а в обновленном приложении будут использоваться как Cloud Pub/Sub, так и Cloud Datastore (через клиентскую библиотеку Cloud NDB). App Engine и оба Cloud API имеют квоты уровня «Всегда бесплатно» , и пока вы не выходите за рамки этих ограничений, вам не придется взимать плату за выполнение этого руководства. Облачные API можно включить либо из облачной консоли, либо из командной строки, в зависимости от ваших предпочтений.

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

Перейдите на страницу библиотеки менеджера API (для нужного проекта) в Cloud Console и найдите API-интерфейсы Cloud Datastore и Cloud Pub/Sub, используя панель поиска в середине страницы:

c7a740304e9d35b.png

Нажмите кнопку «Включить» для каждого API отдельно — вам может быть предложено ввести платежную информацию. Например, это страница библиотеки Cloud Pub/Sub API:

1b6c0a2a73124f6b.jpeg

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

Хотя включение API из консоли визуально информативно, некоторые предпочитают командную строку. Введите команду gcloud services enable pubsub.googleapis.com datastore.googleapis.com чтобы включить оба API одновременно:

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

Вам может быть предложено ввести платежную информацию. Если вы хотите включить другие облачные API и узнать их URI, их можно найти внизу страницы библиотеки каждого API. Например, обратите внимание pubsub.googleapis.com как «Имя службы» внизу страницы Pub/Sub чуть выше.

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

4. Создайте ресурсы Pub/Sub.

Повторяем порядок последовательности рабочего процесса очереди задач из модуля 18:

  1. Модуль 18 использовал файл queue.yaml для создания очереди запроса с именем pullq .
  2. Приложение добавляет задачи в очередь запроса для отслеживания посетителей.
  3. Задачи в конечном итоге обрабатываются работником, арендованным на ограниченное время (час).
  4. Задачи выполняются для подсчета количества недавних посетителей.
  5. Задачи удаляются из очереди после завершения.

Вы собираетесь повторить аналогичный рабочий процесс с Pub/Sub. В следующем разделе представлены базовые термины Pub/Sub и три различных способа создания необходимых ресурсов Pub/Sub.

Очередь задач App Engine (вытягивание) и терминология Cloud Pub/Sub

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

  • Структура данных очередей. При использовании очереди задач данные попадают в очереди извлечения ; при использовании Pub/Sub данные распределяются по темам .
  • Единицы данных в очереди. Задачи извлечения с очередью задач называются сообщениями с Pub/Sub.
  • Обработчики данных: с помощью очереди задач сотрудники получают доступ к задачам извлечения; с Pub/Sub вам нужны подписки/подписчики для получения сообщений
  • Извлечение данных: аренда задачи извлечения аналогична извлечению сообщения из темы (через подписку).
  • Очистка/завершение: удаление задачи очереди задач из очереди извлечения по завершении аналогично подтверждению сообщения Pub/Sub.

Хотя продукт очереди меняется, рабочий процесс остается относительно схожим:

  1. Вместо очереди запроса приложение использует тему с именем pullq .
  2. Вместо добавления задач в очередь запроса приложение отправляет сообщения в тему ( pullq ).
  3. Вместо того, чтобы работник арендует задачи из очереди запроса, подписчик с именем worker извлекает сообщения из темы pullq .
  4. Приложение обрабатывает полезные данные сообщений, увеличивая количество посетителей в хранилище данных.
  5. Вместо удаления задач из очереди запроса приложение подтверждает обработанные сообщения.

При использовании очереди задач настройка включает создание очереди запроса. Для настройки Pub/Sub необходимо создать тему и подписку. В модуле 18 мы обрабатывали queue.yaml вне выполнения приложения; теперь то же самое нужно сделать с Pub/Sub.

Есть три варианта создания тем и подписок:

  1. Из облачной консоли
  2. Из командной строки или
  3. Из кода (короткий скрипт Python)

Выберите один из вариантов ниже и следуйте соответствующим инструкциям, чтобы создать ресурсы Pub/Sub.

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

Чтобы создать тему из Cloud Console, выполните следующие действия:

  1. Перейдите на страницу тем Pub/Sub Topics в облачной консоли.
  2. Нажмите Создать тему вверху; откроется новое диалоговое окно (см. изображение ниже)
  3. В поле «Идентификатор темы» введите pullq .
  4. Отмените выбор всех отмеченных параметров и выберите ключ шифрования, управляемый Google .
  5. Нажмите кнопку Создать тему .

Вот как выглядит диалог создания темы:

a05cfdbf64571ceb.png

Теперь, когда у вас есть тема, необходимо создать подписку на эту тему:

  1. Перейдите на страницу подписки на публикацию и подписку в облачной консоли.
  2. Нажмите «Создать подписку» вверху (см. изображение ниже).
  3. Введите worker в поле «Идентификатор подписки» .
  4. Выберите pullq в раскрывающемся списке «Выбрать тему Cloud Pub/Sub» , отметив его «полный путь», например, projects/PROJECT_ID/topics/pullq
  5. В качестве типа доставки выберите Pull .
  6. Оставьте все остальные параметры как есть и нажмите кнопку «Создать» .

Вот как выглядит экран создания подписки:

c5444375c20b0618.jpeg

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

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

Пользователи Pub/Sub могут создавать темы и подписки с помощью команд gcloud pubsub topics create TOPIC_ID и gcloud pubsub subscriptions create SUBSCRIPTION_ID --topic= TOPIC_ID соответственно. Выполнение их с TOPIC_ID pullq и SUBSCRIPTION_ID worker приводит к следующему выводу для проекта PROJECT_ID :

$ gcloud pubsub topics create pullq
Created topic [projects/PROJECT_ID/topics/pullq].

$ gcloud pubsub subscriptions create worker --topic=pullq
Created subscription [projects/PROJECT_ID/subscriptions/worker].

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

Из кода (короткий скрипт Python)

Другой способ автоматизировать создание тем и подписок — использовать API Pub/Sub в исходном коде. Ниже приведен код сценария maker.py в папке репозитория Модуля 19.

from __future__ import print_function
import google.auth
from google.api_core import exceptions
from google.cloud import pubsub

_, PROJECT_ID = google.auth.default()
TOPIC = 'pullq'
SBSCR = 'worker'
ppc_client = pubsub.PublisherClient()
psc_client = pubsub.SubscriberClient()
TOP_PATH = ppc_client.topic_path(PROJECT_ID, TOPIC)
SUB_PATH = psc_client.subscription_path(PROJECT_ID, SBSCR)

def make_top():
    try:
        top = ppc_client.create_topic(name=TOP_PATH)
        print('Created topic %r (%s)' % (TOPIC, top.name))
    except exceptions.AlreadyExists:
        print('Topic %r already exists at %r' % (TOPIC, TOP_PATH))

def make_sub():
    try:
        sub = psc_client.create_subscription(name=SUB_PATH, topic=TOP_PATH)
        print('Subscription created %r (%s)' % (SBSCR, sub.name))
    except exceptions.AlreadyExists:
        print('Subscription %r already exists at %r' % (SBSCR, SUB_PATH))
    try:
        psc_client.close()
    except AttributeError:  # special Py2 handler for grpcio<1.12.0
        pass

make_top()
make_sub()

Выполнение этого сценария приводит к ожидаемому результату (при условии отсутствия ошибок):

$ python3 maker.py
Created topic 'pullq' (projects/PROJECT_ID/topics/pullq)
Subscription created 'worker' (projects/PROJECT_ID/subscriptions/worker)

Вызов API для создания уже существующих ресурсов приводит к исключению google.api_core.exceptions.AlreadyExists , создаваемому клиентской библиотекой, которое корректно обрабатывается сценарием:

$ python3 maker.py
Topic 'pullq' already exists at 'projects/PROJECT_ID/topics/pullq'
Subscription 'worker' already exists at 'projects/PROJECT_ID/subscriptions/worker'

Если вы новичок в Pub/Sub, дополнительные сведения см. в официальном документе по архитектуре Pub/Sub .

5. Обновить конфигурацию

Обновления конфигурации включают в себя как изменение различных файлов конфигурации, так и создание эквивалента очередей извлечения App Engine, но в рамках экосистемы Cloud Pub/Sub.

Удалить очередь.yaml

Мы полностью отказываемся от очереди задач, поэтому удалите queue.yaml поскольку Pub/Sub не использует этот файл. Вместо создания очереди запроса вы создадите тему Pub/Subподписку ).

требования.txt

Добавьте google-cloud-ndb и google-cloud-pubsub в requirements.txt , чтобы присоединиться к flask из модуля 18. Обновленный файл requirements.txt модуля 19 теперь должен выглядеть следующим образом:

flask
google-cloud-ndb
google-cloud-pubsub

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

app.yaml

Изменения в app.yaml различаются в зависимости от того, используете ли вы Python 2 или обновляетесь до Python 3.

Питон 2

Вышеупомянутое обновление файла requirements.txt добавляет использование клиентских библиотек Google Cloud. Для этого требуется дополнительная поддержка со стороны App Engine, а именно пара встроенных библиотек , setuptools и grpcio . Для использования встроенных библиотек требуется раздел libraries в app.yaml и номера версий библиотек или «последние» для последних версий, доступных на серверах App Engine. В файле app.yaml Модуля 18 пока нет ни одного из этих разделов:

ДО:

runtime: python27
threadsafe: yes
api_version: 1

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

Добавьте раздел libraries в app.yaml вместе с записями для setuptools и grpcio , выбрав их последние версии. Также добавьте запись runtime для Python 3, закомментированную вместе с текущей версией 3.x, например 3.10, на момент написания этой статьи. С этими изменениями app.yaml теперь выглядит так:

ПОСЛЕ:

#runtime: python310
runtime: python27
threadsafe: yes
api_version: 1

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

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

Питон 3

Для пользователей Python 3 и app.yaml все сводится к удалению вещей. В этом разделе вы удалите раздел handlers , директивы threadsafe и api_version и не будете создавать раздел libraries .

Среды выполнения второго поколения не предоставляют встроенных сторонних библиотек , поэтому раздел libraries в app.yaml не нужен. Более того, копирование (иногда называемое вендорингом или самокомплектованием) невстроенных сторонних пакетов больше не требуется. Вам нужно только указать сторонние библиотеки, которые использует ваше приложение, в requirements.txt .

Раздел handlers в app.yaml предназначен для указания обработчиков приложения (скрипта) и статических файлов. Поскольку среда выполнения Python 3 требует, чтобы веб-платформы выполняли собственную маршрутизацию, все обработчики сценариев необходимо изменить на auto . Если ваше приложение (например, Модуль 18) не обслуживает статические файлы, все маршруты будут auto , что сделает их нерелевантными. В результате раздел handlers также не нужен, поэтому удалите его.

Наконец, ни директивы threadsafe , ни api_version не используются в Python 3, поэтому удалите и их. Суть в том, что вам следует удалить все разделы app.yaml , чтобы осталась только директива runtime , указывающая современную версию Python 3, например, 3.10. Вот как выглядит app.yaml до и после этих обновлений:

ДО:

runtime: python27
threadsafe: yes
api_version: 1

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

ПОСЛЕ:

runtime: python310

Для тех, кто не готов удалить все из своего app.yaml для Python 3, мы предоставили альтернативный файл app3.yaml в папке репозитория Модуля 19. Если вы хотите использовать его вместо этого для развертываний, обязательно добавьте это имя файла в конец вашей команды: gcloud app deploy app3.yaml (в противном случае по умолчанию будет использоваться файл app.yaml Python 2, который вы развернете). оставлен без изменений).

appengine_config.py

Если вы обновляетесь до Python 3, appengine_config.py не нужен, поэтому удалите его. Причина, по которой в этом нет необходимости, заключается в том, что для поддержки сторонних библиотек требуется указать их только в requirements.txt . Пользователи Python 2, читайте дальше.

Модуль 18 appengine_config.py содержит соответствующий код для поддержки сторонних библиотек , например Flask и клиентских библиотек Cloud, только что добавленных в requirements.txt :

ДО:

from google.appengine.ext import vendor

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

Однако одного этого кода недостаточно для поддержки только что добавленных встроенных библиотек ( setuptools , grpcio ). Необходимо еще несколько строк, поэтому обновите appengine_config.py , чтобы он выглядел так:

ПОСЛЕ:

import pkg_resources
from google.appengine.ext import vendor

# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
# Add libraries to pkg_resources working set to find the distribution.
pkg_resources.working_set.add_entry(PATH)

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

Другие обновления конфигурации

Если у вас есть папка lib , удалите ее. Если вы пользователь Python 2, пополните папку lib , выполнив следующую команду:

pip install -t lib -r requirements.txt  # or pip2

Если в вашей системе разработки установлены Python 2 и 3, возможно, вам придется использовать pip2 вместо pip .

6. Измените код приложения.

В этом разделе представлены обновления основного файла приложения main.py , заменяющие использование очередей извлечения очереди задач App Engine на Cloud Pub/Sub. В веб-шаблоне templates/index.html изменений нет. Оба приложения должны работать одинаково, отображая одни и те же данные.

Обновление импорта и инициализации

Есть несколько обновлений импорта и инициализации:

  1. Для импорта замените App Engine NDB и Task Queue на Cloud NDB и Pub/Sub.
  2. Переименуйте pullq из имени QUEUE в имя TOPIC .
  3. В задачах извлечения работник арендовал их на час, но в случае с Pub/Sub тайм-ауты измеряются для каждого сообщения, поэтому удалите константу HOUR .
  4. Облачные API требуют использования клиента API, поэтому инициируйте их для Cloud NDB и Cloud Pub/Sub, причем последний предоставляет клиентов как для тем, так и для подписок.
  5. Для Pub/Sub требуется идентификатор облачного проекта, поэтому импортируйте и получите его из google.auth.default() .
  6. Pub/Sub требует «полных путей» для тем и подписок, поэтому создавайте их, используя удобные функции *_path() .

Ниже приведены импорт и инициализация из Модуля 18, а затем показано, как должны выглядеть разделы после реализации вышеуказанных изменений, при этом большая часть нового кода представляет собой различные ресурсы Pub/Sub:

ДО:

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

HOUR = 3600
LIMIT = 10
TASKS = 1000
QNAME = 'pullq'
QUEUE = taskqueue.Queue(QNAME)
app = Flask(__name__)

ПОСЛЕ:

from flask import Flask, render_template, request
import google.auth
from google.cloud import ndb, pubsub

LIMIT = 10
TASKS = 1000
TOPIC = 'pullq'
SBSCR = 'worker'

app = Flask(__name__)
ds_client  = ndb.Client()
ppc_client = pubsub.PublisherClient()
psc_client = pubsub.SubscriberClient()
_, PROJECT_ID = google.auth.default()
TOP_PATH = ppc_client.topic_path(PROJECT_ID, TOPIC)
SUB_PATH = psc_client.subscription_path(PROJECT_ID, SBSCR)

Посетите обновления модели данных

Модель данных Visit не меняется. Доступ к хранилищу данных требует явного использования диспетчера контекста клиента API Cloud NDB, ds_client.context() . В коде это означает, что вы оборачиваете вызовы Datastore как в store_visit() так и fetch_visits() внутри Python with блоков. Это обновление идентично тому, что описано в Модуле 2.

Наиболее важным изменением для Pub/Sub является замена постановки в очередь задачи извлечения из очереди задач публикацией сообщения Pub/Sub в теме pullq . Ниже приведен код до и после внесения этих обновлений:

ДО:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)

def store_visit(remote_addr, user_agent):
    'create new Visit in Datastore and queue request to bump visitor count'
    Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
    QUEUE.add(taskqueue.Task(payload=remote_addr, method='PULL'))

def fetch_visits(limit):
    'get most recent visits'
    return Visit.query().order(-Visit.timestamp).fetch(limit)

ПОСЛЕ:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)

def store_visit(remote_addr, user_agent):
    'create new Visit in Datastore and queue request to bump visitor count'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
    ppc_client.publish(TOP_PATH, remote_addr.encode('utf-8'))

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

Обновления модели данных VisitorCount

Модель данных VisitorCount не меняется и выполняет fetch_counts() за исключением помещения запроса к хранилищу данных в блок with , как показано ниже:

ДО:

class VisitorCount(ndb.Model):
    visitor = ndb.StringProperty(repeated=False, required=True)
    counter = ndb.IntegerProperty()

def fetch_counts(limit):
    'get top visitors'
    return VisitorCount.query().order(-VisitorCount.counter).fetch(limit)

ПОСЛЕ:

class VisitorCount(ndb.Model):
    visitor = ndb.StringProperty(repeated=False, required=True)
    counter = ndb.IntegerProperty()

def fetch_counts(limit):
    'get top visitors'
    with ds_client.context():
        return VisitorCount.query().order(-VisitorCount.counter).fetch(limit)

Обновить рабочий код

Рабочий код обновляется вплоть до замены NDB на Cloud NDB и очереди задач на Pub/Sub, но его рабочий процесс остается прежним.

  1. Оберните вызовы хранилища данных в контекстном менеджере Cloud NDB with .
  2. Очистка очереди задач включает в себя удаление всех задач из очереди запроса. При использовании Pub/Sub «идентификаторы подтверждения» собираются в acks , а затем в конце удаляются/подтверждаются.
  3. Задачи извлечения очереди задач арендуются аналогично тому, как извлекаются сообщения Pub/Sub. Хотя удаление задач извлечения выполняется с помощью самих объектов задач, сообщения Pub/Sub удаляются через их идентификаторы подтверждения.
  4. Полезные данные сообщений Pub/Sub требуют байтов (а не строк Python), поэтому при публикации в теме и извлечении сообщений из темы используется некоторая кодировка и декодирование UTF-8 соответственно.

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

ДО:

@app.route('/log')
def log_visitors():
    'worker processes recent visitor counts and updates them in Datastore'
    # tally recent visitor counts from queue then delete those tasks
    tallies = {}
    tasks = QUEUE.lease_tasks(HOUR, TASKS)
    for task in tasks:
        visitor = task.payload
        tallies[visitor] = tallies.get(visitor, 0) + 1
    if tasks:
        QUEUE.delete_tasks(tasks)

    # increment those counts in Datastore and return
    for visitor in tallies:
        counter = VisitorCount.query(VisitorCount.visitor == visitor).get()
        if not counter:
            counter = VisitorCount(visitor=visitor, counter=0)
            counter.put()
        counter.counter += tallies[visitor]
        counter.put()
    return 'DONE (with %d task[s] logging %d visitor[s])\r\n' % (
            len(tasks), len(tallies))

ПОСЛЕ:

@app.route('/log')
def log_visitors():
    'worker processes recent visitor counts and updates them in Datastore'
    # tally recent visitor counts from queue then delete those tasks
    tallies = {}
    acks = set()
    rsp = psc_client.pull(subscription=SUB_PATH, max_messages=TASKS)
    msgs = rsp.received_messages
    for rcvd_msg in msgs:
        acks.add(rcvd_msg.ack_id)
        visitor = rcvd_msg.message.data.decode('utf-8')
        tallies[visitor] = tallies.get(visitor, 0) + 1
    if acks:
        psc_client.acknowledge(subscription=SUB_PATH, ack_ids=acks)
    try:
        psc_client.close()
    except AttributeError:  # special handler for grpcio<1.12.0
        pass

    # increment those counts in Datastore and return
    if tallies:
        with ds_client.context():
            for visitor in tallies:
                counter = VisitorCount.query(VisitorCount.visitor == visitor).get()
                if not counter:
                    counter = VisitorCount(visitor=visitor, counter=0)
                    counter.put()
                counter.counter += tallies[visitor]
                counter.put()
    return 'DONE (with %d task[s] logging %d visitor[s])\r\n' % (
            len(msgs), len(tallies))

В главном обработчике приложения root() изменений нет. Никаких изменений не требуется и в файле HTML-шаблона, templates/index.html , поэтому он включает в себя все необходимые обновления. Поздравляем с появлением нового приложения Модуля 19 с использованием Cloud Pub/Sub!

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

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

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

Убедитесь, что вы уже создали тему pullq и worker подписку. Если это выполнено и ваш пример приложения готов к работе, разверните его с помощью gcloud app deploy . Вывод должен быть идентичен приложению Модуля 18, за исключением того, что вы успешно заменили весь базовый механизм организации очередей:

b667551dcbab1a09.png

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

Это можно выполнить с помощью серверной службы App Engine, задания cron , просмотра /log или отправки HTTP-запроса из командной строки. Вот один из примеров выполнения без вызова рабочего кода с помощью curl (замените PROJECT_ID ):

$ curl https://PROJECT_ID.appspot.com/log
DONE (with 1 task[s] logging 1 visitor[s])

Обновленное количество будет отражено при следующем посещении веб-сайта. Вот и все!

Очистить

Общий

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

Для полной информации: развертывание на бессерверной вычислительной платформе Google Cloud, такой как App Engine, требует незначительных затрат на сборку и хранение . Cloud Build имеет собственную бесплатную квоту, как и 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 Pub/Sub имеют уровень бесплатного пользования; определите общее использование, чтобы получить лучшее представление о финансовых последствиях, и посетите страницу с ценами для получения более подробной информации.
  • Служба хранилища данных App Engine предоставляется Cloud Datastore (Cloud Firestore в режиме хранилища данных), который также имеет уровень бесплатного пользования; дополнительную информацию см. на странице цен .

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

Помимо этого руководства, следует рассмотреть и другие модули миграции, направленные на отказ от устаревших комплексных услуг:

  • Модуль 2. Переход с App Engine ndb на Cloud NDB.
  • Модули 7–9 : переход из очереди задач App Engine (push-задачи) в облачные задачи.
  • Модули 12–13 : миграция с Memcache App Engine на Cloud Memorystore.
  • Модули 15–16 : миграция из App Engine Blobstore в облачное хранилище.

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

  • Миграция с App Engine на облачные функции: см. Модуль 11.
  • Миграция с App Engine на Cloud Run: см. Модуль 4 , чтобы контейнеризировать приложение с помощью Docker, или Модуль 5 , чтобы сделать это без контейнеров, знаний Docker или Dockerfile s.

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

Независимо от того, какой модуль миграции вы рассматриваете следующим, весь контент Serverless Migration Station (лаборатории кода, видео, исходный код [при наличии]) можно получить в его репозитории с открытым исходным кодом . README репозитория также содержит рекомендации о том, какие миграции следует учитывать, а также любой соответствующий «порядок» модулей миграции.

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

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

Проблемы/отзывы Codelabs

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

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

Ссылки на папки репозитория для Модуля 18 (НАЧАЛО) и Модуля 19 (ФИНИШ) можно найти в таблице ниже.

Кодлаб

Питон 2

Питон 3

Модуль 18

код

(н/д)

Модуль 19 (это кодовая лаборатория)

код

(то же самое, что и Python 2, за исключением использования app3.yaml, если вы не обновили app.yaml, как описано выше)

Интернет-ссылки

Ниже приведены ресурсы, относящиеся к этому руководству:

Очередь задач App Engine

Облачный паб/саб

App Engine NDB и Cloud NDB (хранилище данных)

Платформа App Engine

Другая информация об облаке

Видео

Лицензия

Эта работа распространяется под лицензией Creative Commons Attribution 2.0 Generic License.