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

1. Обзор

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

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

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

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

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

Опрос

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

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

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

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

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

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

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

Чтобы выполнить миграцию из задач извлечения очереди задач App Engine, добавьте его использование в существующее приложение Flask и App Engine NDB, созданное на основе кода модуля 1 . Пример приложения отображает самые последние посещения конечного пользователя. Это нормально, но еще интереснее отслеживать посетителей, чтобы увидеть, кто посещает больше всего.

Хотя мы могли бы использовать push-задачи для подсчета посетителей, мы хотим разделить ответственность между примером приложения, чья работа заключается в регистрации посещений и немедленном реагировании на запросы пользователей, и назначенным «работником», чья работа заключается в подсчете количества посетителей. за пределами обычного рабочего процесса запрос-ответ.

Чтобы реализовать этот дизайн, мы добавляем в основное приложение использование очередей извлечения , а также поддерживаем рабочие функции. Рабочий может выполняться как отдельный процесс (например, серверный экземпляр или код, выполняющийся на постоянно работающей виртуальной машине), задание cron или базовый HTTP-запрос командной строки с использованием curl или wget . После этой интеграции вы можете перенести приложение в Cloud Pub/Sub в следующей лаборатории кода (Модуль 19).

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

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

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

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

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

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

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

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

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

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

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

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

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 ) вносить изменения не требуется. Вместо этого добавьте новый файл queue.yaml со следующим содержимым, поместив его в тот же каталог верхнего уровня:

queue:
- name: pullq
  mode: pull

В queue.yaml указаны все очереди задач, существующие для вашего приложения (кроме очереди [push] default , которая автоматически создается App Engine). В данном случае существует только одна очередь запроса с именем pullq . App Engine требует, чтобы директива mode была указана как pull , в противном случае по умолчанию создается очередь push. Подробнее о создании очередей pull читайте в документации . Также см. справочную страницу queue.yaml для получения информации о других параметрах.

Разверните этот файл отдельно от вашего приложения. Вы по-прежнему будете использовать gcloud app deploy , но также предоставите queue.yaml в командной строке:

$ gcloud app deploy queue.yaml
Configurations to update:

descriptor:      [/tmp/mod18-gaepull/queue.yaml]
type:            [task queues]
target project:  [my-project]

WARNING: Caution: You are updating queue configuration. This will override any changes performed using 'gcloud tasks'. More details at
https://cloud.google.com/tasks/docs/queue-yaml

Do you want to continue (Y/n)?

Updating config [queue]...⠹WARNING: We are using the App Engine app location (us-central1) as the default location. Please use the "--location" flag if you want to use a different location.
Updating config [queue]...done.

Task queues have been updated.

Visit the Cloud Platform Console Task Queues page to view your queues and cron jobs.
$

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

В этом разделе представлены обновления следующих файлов:

  • main.py — добавить использование очередей извлечения в основное приложение.
  • templates/index.html — обновите веб-шаблон для отображения новых данных.

Импорт и константы

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

  • Добавьте импорт библиотеки Task Queue google.appengine.api.taskqueue .
  • Добавьте три константы для поддержки аренды максимального количества задач извлечения ( TASKS ) на час ( HOUR ) из нашей очереди извлечения ( QUEUE ).
  • Добавьте константу для отображения последних посещений, а также самых популярных посетителей ( LIMIT ).

Ниже приведен исходный код и то, как он выглядит после внесения этих обновлений:

ДО:

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

app = Flask(__name__)

ПОСЛЕ:

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__)

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

Модель данных Visit остается прежней, как и запрос посещений для отображения в fetch_visits() . Единственное изменение, необходимое в этой части кода, — это store_visit() . Помимо регистрации посещения, добавьте задачу в очередь запроса с IP-адресом посетителя, чтобы работник мог увеличить счетчик посетителей.

ДО:

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

ПОСЛЕ:

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)

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

Добавьте модель данных VisitorCount для отслеживания посетителей; он должен иметь поля для самого visitor , а также целочисленный counter для отслеживания количества посещений. Затем добавьте новую функцию (альтернативно это может быть classmethod Python) с именем fetch_counts() чтобы запрашивать и возвращать самых популярных посетителей в порядке от большего к меньшему. Добавьте класс и функцию прямо под телом fetch_visits() :

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

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

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

Добавьте новую функцию log_visitors() для регистрации посетителей с помощью запроса GET к /log . Он использует словарь/хэш для отслеживания последнего количества посетителей, беря на себя как можно больше задач на час. Для каждой задачи подсчитываются все посещения одного и того же посетителя. Имея под рукой подсчеты, приложение затем обновляет все соответствующие объекты VisitorCount , уже находящиеся в хранилище данных, или при необходимости создает новые. Последний шаг возвращает простое текстовое сообщение, указывающее, сколько посетителей зарегистрировалось и сколько обработанных задач. Добавьте эту функцию в main.py прямо под fetch_counts() :

@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))

Обновить основной обработчик новыми отображаемыми данными.

Чтобы отобразить самых популярных посетителей, обновите основной обработчик root() , чтобы он вызывал fetch_counts() . Кроме того, шаблон будет обновлен, чтобы отображать количество самых популярных посетителей и последних посещений. Упакуйте количество посетителей вместе с самыми последними посещениями из вызова fetch_visits() и поместите их в единый context для передачи в веб-шаблон. Ниже приведен код до и после внесения этого изменения:

ДО:

@app.route('/')
def root():
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)
    return render_template('index.html', visits=visits)

ПОСЛЕ:

@app.route('/')
def root():
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    context = {
        'limit':  LIMIT,
        'visits': fetch_visits(LIMIT),
        'counts': fetch_counts(LIMIT),
    }
    return render_template('index.html', **context)

Это все изменения, необходимые для main.py , и вот графическое представление этих обновлений для иллюстративных целей, чтобы дать вам общее представление об изменениях, которые вы вносите в main.py :

ad5fd3345efc13d0.png

Обновить веб-шаблон новыми отображаемыми данными.

Веб-шаблон templates/index.html требует обновления для отображения самых популярных посетителей в дополнение к обычной полезной нагрузке самых последних посетителей. Перенесите данные о самых популярных посетителях и их количество в таблицу вверху страницы и продолжайте отображать самые последние посещения, как и раньше. Единственное другое изменение — указать число, отображаемое через limit переменную, а не жестко запрограммировать это число. Вот обновления, которые вам следует внести в свой веб-шаблон:

ДО:

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

ПОСЛЕ:

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

<h1>VisitMe example</h1>

<h3>Top {{ limit }} visitors</h3>
<table border=1 cellspacing=0 cellpadding=2>
    <tr><th>Visitor</th><th>Visits</th></tr>
{% for count in counts %}
    <tr><td>{{ count.visitor|e }}</td><td align="center">{{ count.counter }}</td></tr>
{% endfor %}
</table>

<h3>Last {{ limit }} visits</h3>
<ul>
{% for visit in visits %}
    <li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>

На этом завершаются необходимые изменения, добавляющие использование задач извлечения очереди задач App Engine в пример приложения Модуля 1. Теперь ваш каталог представляет собой пример приложения Модуля 18 и должен содержать следующие файлы:

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

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

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

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

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

b667551dcbab1a09.png

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

Вы можете выполнить задачу, вызвав /log различными способами:

Например, если вы используете curl для отправки запроса GET в /log , ваш вывод будет выглядеть следующим образом, если вы указали свой PROJECT_ID :

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

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

Поздравляем с завершением этой лабораторной работы по успешному добавлению использования службы очереди запросов App Engine Task Queue в пример приложения. Теперь он готов к переходу на Cloud Pub/Sub, Cloud NDB и Python 3 в модуле 19.

Очистить

Общий

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Кодлаб

Питон 2

Питон 3

Модуль 1

код

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

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

код

Н/Д

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

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

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

Платформа App Engine

Документация App Engine

Среда выполнения Python 2 App Engine (стандартная среда)

Среда выполнения Python 3 App Engine (стандартная среда)

Различия между средами выполнения App Engine Python 2 и 3 (стандартная среда)

Руководство по переходу с Python 2 на App Engine (стандартная среда)

Информация о ценах и квотах App Engine

Запуск платформы App Engine второго поколения (2018 г.)

Долгосрочная поддержка устаревших сред выполнения

Примеры миграции документации

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

Видео

Лицензия

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