Как использовать очередь задач App Engine (push-задачи) в приложениях Flask (модуль 7)

1. Обзор

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

В этой лаборатории кода вы узнаете, как использовать задачи принудительной отправки из очереди задач App Engine в примере приложения из лаборатории кода модуля 1 . Сообщение в блоге Модуля 7 и видео дополняют это руководство, предоставляя краткий обзор содержания этого руководства.

В этом модуле мы добавим использование задач push , а затем перенесем это использование в облачные задачи в модуле 8 и более поздних версиях, в Python 3 и в облачное хранилище данных в модуле 9. Те, кто использует очереди задач для задач извлечения , перейдут в Cloud Pub/Sub и вместо этого следует обратиться к модулям 18–19.

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

  • Используйте API очереди задач App Engine или встроенную службу.
  • Добавьте использование push-задач в базовое приложение Python 2 Flask App Engine NDB.

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

Опрос

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

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

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

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

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

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

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

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

Миграция задач по запросу рассматривается в модулях миграции 18–19, а модули 7–9 посвящены миграции задач по запросу. Чтобы перейти от push-задач App Engine Task Queue, добавьте его использование в существующее приложение Flask и App Engine NDB, созданное на основе кода модуля 1 . В этом приложении новый просмотр страницы регистрирует новое посещение и отображает самые последние посещения пользователя. Поскольку более старые посещения больше никогда не отображаются и занимают место в хранилище данных, мы создадим задачу push для автоматического удаления самых старых посещений. Далее в модуле 8 мы перенесем это приложение из очереди задач в облачные задачи.

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

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

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

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

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

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

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

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

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

Одним из обязательных условий для этой лаборатории кода является наличие рабочего приложения App Engine Модуля 1: заполните лабораторию кода Модуля 1 (рекомендуется) или скопируйте приложение Модуля 1 из репозитория. Независимо от того, используете ли вы свой или наш, мы «НАЧНЕМ» с кода Модуля 1. Эта лаборатория кода проведет вас через каждый шаг, завершая кодом, похожим на код, который находится в папке репозитория Модуля 7 «FINISH».

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

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

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

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

  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. Убедитесь, что приложение Модуля 1 работает как положено, без проблем с отображением последних посещений (показано ниже).

a7a9d2b80d706a2b.png

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

В стандартные файлы конфигурации App Engine ( app.yaml , requirements.txt , appengine_config.py ) вносить изменения не требуется.

5. Измените файлы приложения.

Основной файл приложения — main.py , и все обновления в этом разделе относятся к этому файлу. Также имеется небольшое обновление веб-шаблона templates/index.html . Вот изменения, которые необходимо реализовать в этом разделе:

  1. Обновить импорт
  2. Добавить push-задачу
  3. Добавить обработчик задач
  4. Обновить веб-шаблон

1. Обновить импорт

Импорт google.appengine.api.taskqueue обеспечивает функциональность очереди задач. Также требуются некоторые пакеты стандартной библиотеки Python:

  • Поскольку мы добавляем задачу по удалению самых старых посещений, приложению придется иметь дело с временными метками, то есть с использованием time и datetime и времени.
  • Чтобы регистрировать полезную информацию о выполнении задач, нам понадобится logging .

Добавив весь этот импорт, ниже показано, как выглядит ваш код до и после этих изменений:

ДО:

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

ПОСЛЕ:

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

2. Добавить задачу push (сопоставить данные для задачи, поставить в очередь новую задачу)

В документации по очереди отправки указано: «Чтобы обработать задачу, необходимо добавить ее в очередь отправки. App Engine предоставляет очередь отправки по умолчанию с именем default , которая настроена и готова к использованию с настройками по умолчанию. Если хотите, вы можете просто добавляйте все свои задачи в очередь по умолчанию без необходимости создавать и настраивать другие очереди». В этой лаборатории кода для краткости используется очередь default . Дополнительные сведения об определении собственных очередей push-уведомлений с одинаковыми или разными характеристиками см. в документации по созданию очередей push-уведомлений .

Основная цель этой лаборатории кода — добавить задачу (в очередь push default ), задача которой — удалять из хранилища данных старые посещения, которые больше не отображаются. Базовое приложение регистрирует каждое посещение (запрос GET к / ), создавая новый объект Visit , а затем извлекает и отображает самые последние посещения. Ни одно из самых старых посещений больше никогда не будет отображаться или использоваться, поэтому задача push удаляет все посещения старше самого старого отображаемого . Для этого поведение приложения необходимо немного изменить:

  1. При запросе самых последних посещений вместо немедленного возврата этих посещений измените приложение, чтобы оно сохраняло временную метку последнего Visit , самого старого отображаемого посещения — можно безопасно удалить все посещения старше этого.
  2. Создайте задачу push с этой меткой времени в качестве полезной нагрузки и направьте ее обработчику задачи, доступному через HTTP POST в /trim . В частности, используйте стандартные утилиты Python для преобразования временной метки хранилища данных и отправки ее (в виде числа с плавающей запятой) в задачу, а также регистрации ее (в виде строки) и возврата этой строки в качестве контрольного значения для отображения пользователю.

Все это происходит в fetch_visits() , и вот как это выглядит до и после внесения этих обновлений:

ДО:

def fetch_visits(limit):
    return (v.to_dict() for v in Visit.query().order(
            -Visit.timestamp).fetch(limit))

ПОСЛЕ:

def fetch_visits(limit):
    'get most recent visits and add task to delete older visits'
    data = Visit.query().order(-Visit.timestamp).fetch(limit)
    oldest = time.mktime(data[-1].timestamp.timetuple())
    oldest_str = time.ctime(oldest)
    logging.info('Delete entities older than %s' % oldest_str)
    taskqueue.add(url='/trim', params={'oldest': oldest})
    return (v.to_dict() for v in data), oldest_str

3. Добавьте обработчик задачи (код, вызываемый при запуске задачи).

Хотя удаление старых посещений можно было легко выполнить с помощью fetch_visits() , учтите, что эта функция не имеет особого отношения к конечному пользователю. Это вспомогательная функциональность и хороший кандидат для асинхронной обработки вне стандартных запросов приложений. Конечный пользователь получит выгоду от более быстрых запросов, поскольку в хранилище данных будет меньше информации. Создайте новую функцию trim() , вызываемую через POST запрос очереди задач к /trim , которая выполняет следующие действия:

  1. Извлекает полезную нагрузку временной метки «самого старого посещения».
  2. Выполняет запрос к хранилищу данных, чтобы найти все объекты старше этой отметки времени.
  3. Выбирает более быстрый запрос «только ключи», поскольку фактические пользовательские данные не требуются.
  4. Регистрирует количество объектов, которые необходимо удалить (включая ноль).
  5. Вызывает ndb.delete_multi() для удаления любых объектов (в противном случае пропускается).
  6. Возвращает пустую строку (вместе с неявным кодом возврата HTTP 200).

Вы можете увидеть все это в trim() ниже. Добавьте его в main.py сразу после fetch_visits() :

@app.route('/trim', methods=['POST'])
def trim():
    '(push) task queue handler to delete oldest visits'
    oldest = request.form.get('oldest', type=float)
    keys = Visit.query(
            Visit.timestamp < datetime.fromtimestamp(oldest)
    ).fetch(keys_only=True)
    nkeys = len(keys)
    if nkeys:
        logging.info('Deleting %d entities: %s' % (
                nkeys, ', '.join(str(k.id()) for k in keys)))
        ndb.delete_multi(keys)
    else:
        logging.info('No entities older than: %s' % time.ctime(oldest))
    return ''   # need to return SOME string w/200

4. Обновите веб-шаблон.

Обновите веб-шаблон templates/index.html с помощью этого условия Jinja2, чтобы отображать самую старую временную метку, если эта переменная существует:

{% if oldest is defined %}
    <b>Deleting visits older than:</b> {{ oldest }}</p>
{% endif %}

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

<!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>

{% if oldest is defined %}
    <b>Deleting visits older than:</b> {{ oldest }}</p>
{% endif %}
</body>
</html>

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

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

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

Разверните приложение с помощью gcloud app deploy . Вывод должен быть идентичен приложению Модуля 1, за исключением новой строки внизу, показывающей, какие посещения будут удалены:

4aa8a2cb5f527079.png

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

Очистить

Общий

Если вы закончили, мы рекомендуем вам отключить приложение 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 », если ваше приложение размещено в США.

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

Специально для этой кодовой лаборатории

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

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

В ходе этой «миграции» вы добавили использование push-очереди очереди задач в пример приложения Модуля 1, добавив поддержку отслеживания посетителей, в результате чего появился пример приложения Модуля 7. Следующая миграция научит вас, как перейти с push-задач App Engine на облачные задачи, если вы решите это сделать. Осенью 2021 года пользователям больше не придется переходить на Cloud Tasks при обновлении до Python 3. Подробнее об этом читайте в следующем разделе.

Если вы все же хотите перейти к облачным задачам, следующим будет код модуля 8 . Помимо этого, следует учитывать дополнительные миграции, такие как Cloud Datastore, Cloud Memorystore, Cloud Storage или Cloud Pub/Sub (очереди извлечения). Также возможен переход между продуктами в Cloud Run и Cloud Functions. Доступ ко всему содержимому Serverless Migration Station (кодовые лаборатории, видео, исходный код [при наличии]) можно получить в репозитории с открытым исходным кодом .

7. Миграция на Python 3

Осенью 2021 года команда App Engine расширила поддержку многих входящих в комплект служб до сред выполнения 2-го поколения (изначально доступной только в средах выполнения 1-го поколения), что означает, что вам больше не нужно переходить от связанных служб, таких как App Engine Task Queue, к автономному облаку или Сторонние эквиваленты, такие как Cloud Tasks, при переносе вашего приложения на Python 3. Другими словами, вы можете продолжать использовать Task Queue в приложениях Python 3 App Engine, если вы модифицируете код для доступа к связанным службам из сред выполнения следующего поколения .

Вы можете узнать больше о том, как перенести использование встроенных сервисов на Python 3, в лабораторной работе по коду Модуля 17 и соответствующем видеоролике. Хотя эта тема выходит за рамки Модуля 7, ниже приведены ссылки на версии Python 3 приложений Модуля 1 и 7, перенесенные на Python 3 и по-прежнему использующие NDB App Engine и Очередь задач.

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

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

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

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

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

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

Кодлаб

Питон 2

Питон 3

Модуль 1

код

код (не представлен в этом руководстве)

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

код

код (не представлен в этом руководстве)

Интернет-ресурсы

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

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

Платформа App Engine

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

Видео

Лицензия

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