Как ставить функции в очередь с помощью Cloud Tasks (1-го поколения)

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

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

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

Firebase SDK для Cloud Functions for Firebase версии 3.20.1 и более поздних взаимодействует с Firebase Admin SDK версии 10.2.0 и более поздних, чтобы поддерживать функции очереди задач.

При использовании функций очереди задач с Firebase может взиматься плата за обработку Cloud Tasks. Подробнее о ценах на Cloud Tasks…

Как создать функции очереди задач

Чтобы использовать функции очереди задач, выполните следующие действия:

  1. Напишите функцию очереди задач, используя Firebase SDK для Cloud Functions.
  2. Протестируйте функцию, активировав ее с помощью HTTP-запроса.
  3. Разверните функцию с помощью интерфейса командной строки Firebase. При первом развертывании функции очереди задач интерфейс командной строки создаст очередь задач в Cloud Tasks с параметрами (ограничение частоты запросов и повторные попытки), указанными в исходном коде.
  4. Добавьте задачи в новую очередь, передав параметры для настройки расписания выполнения, если это необходимо. Для этого напишите код с помощью Admin SDK и разверните его в Cloud Functions for Firebase.

Как писать функции очереди задач

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

Как настроить функции очереди задач

Функции очереди задач имеют множество настроек, позволяющих точно контролировать ограничения скорости и поведение при повторных попытках:

exports.backupApod = functions
    .runWith( {secrets: ["NASA_API_KEY"]})
    .tasks.taskQueue({
      retryConfig: {
        maxAttempts: 5,
        minBackoffSeconds: 60,
      },
      rateLimits: {
        maxConcurrentDispatches: 6,
      },
    }).onDispatch(async (data) => {
  • retryConfig.maxAttempts=5: каждая задача в очереди задач автоматически повторяется до пяти раз. Это помогает устранять временные ошибки, например сбои в сети или временное нарушение работы зависимого внешнего сервиса.
  • retryConfig.minBackoffSeconds=60 – каждая задача повторяется не раньше, чем через 60 секунд после предыдущей попытки. Это обеспечивает большой буфер между каждой попыткой, поэтому мы не спешим исчерпать пять попыток слишком быстро.
  • rateLimits.maxConcurrentDispatch=6: одновременно может быть назначено не более шести задач. Это обеспечивает стабильный поток запросов к базовой функции и помогает сократить количество активных экземпляров и холодных запусков.

Как тестировать функции очереди задач

В большинстве случаев для тестирования функций очереди задач лучше всего подходит эмулятор Cloud Functions. Чтобы узнать, как подготовить приложение к эмуляции функций очереди задач, ознакомьтесь с документацией по Emulator Suite.

Кроме того, функции очереди задач представлены в виде простых HTTP-функций в Firebase Local Emulator Suite. Вы можете протестировать функцию эмулируемой задачи, отправив HTTP-запрос POST с полезной нагрузкой в формате JSON:

 # start the Firebase Emulators
 firebase emulators:start

 # trigger the emulated task queue function
 curl \
  -X POST                                            # An HTTP POST request...
  -H "content-type: application/json" \              # ... with a JSON body
  http://localhost:$PORT/$PROJECT_ID/$REGION/$NAME \ # ... to function url
  -d '{"data": { ... some data .... }}'              # ... with JSON encoded data

Как развернуть функции очереди задач

Разверните функцию очереди задач с помощью интерфейса командной строки Firebase:

$ firebase deploy --only functions:backupApod

При первом развертывании функции очереди задач CLI создает очередь задач в Cloud Tasks с параметрами (ограничение частоты запросов и повторные попытки), указанными в исходном коде.

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

Как добавить в очередь функции очереди задач

Функции очереди задач можно ставить в очередь в Cloud Tasks из доверенной серверной среды, например Cloud Functions for Firebase, с помощью Firebase Admin SDK для Node.js. Если вы раньше не работали с Admin SDK, начните с добавления Firebase на сервер.

В типичном процессе Admin SDK создает новую задачу, добавляет ее в очередь Cloud Tasks и задает конфигурацию задачи:

exports.enqueueBackupTasks = functions.https.onRequest(
async (_request, response) => {
  const queue = getFunctions().taskQueue("backupApod");
  const enqueues = [];
  for (let i = 0; i <= 10; i += 1) {
    // Enqueue each task with i*60 seconds delay. Our task queue function
    // should process ~1 task/min.
    const scheduleDelaySeconds = i * 60 
    enqueues.push(
        queue.enqueue(
          { id: `task-${i}` },
          {
            scheduleDelaySeconds,
            dispatchDeadlineSeconds: 60 * 5 // 5 minutes
          },
        ),
    );
  }
  await Promise.all(enqueues);
  response.sendStatus(200);

});
  • scheduleDelaySeconds: в примере кода выполнение задач распределяется по времени. Для N-й задачи задана задержка в N минут. Это означает, что будет запускаться примерно одна задача в минуту. Обратите внимание, что вы также можете использовать атрибут "дата начала действия промоакции" scheduleTime, если хотите, чтобы атрибут "цена со скидкой" Cloud Tasks активировал задачу в определенное время.
  • dispatchDeadlineSeconds: максимальное время, в течение которого Cloud Tasks будет ждать завершения задачи. Cloud Tasks будет повторять задачу в соответствии с настройками очереди или до истечения срока. В примере очередь настроена на повтор задачи до пяти раз, но задача автоматически отменяется, если весь процесс (включая попытки повтора) занимает более пяти минут.

Устранение неполадок

Как включить ведение журналов Cloud Tasks

Журналы из Cloud Tasks содержат полезную диагностическую информацию, например статус запроса, связанного с задачей. По умолчанию журналы из Cloud Tasks отключены, поскольку они могут генерировать большой объем данных в вашем проекте. Мы рекомендуем включить журналы отладки, когда вы активно разрабатываете и отлаживаете функции очереди задач. Подробнее о том, как включить ведение журнала…

Права доступа IAM

При постановке задач в очередь или при попытке Cloud Tasks вызвать функции очереди задач могут возникать ошибки PERMISSION DENIED. Убедитесь, что в вашем проекте есть следующие привязки IAM:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member=serviceAccount:${PROJECT_ID}@appspot.gserviceaccount.com \
  --role=roles/cloudtasks.enqueuer
  • У аккаунта, используемого для добавления задач в очередь Cloud Tasks, должно быть разрешение на использование сервисного аккаунта, связанного с задачей в Cloud Tasks.

    В примере это сервисный аккаунт по умолчанию App Engine.

Инструкции по добавлению сервисного аккаунта по умолчанию App Engine в качестве пользователя сервисного аккаунта по умолчанию App Engine можно найти в документации по Cloud IAM Google Cloud.

gcloud functions add-iam-policy-binding $FUNCTION_NAME \
  --region=us-central1 \
  --member=serviceAccount:${PROJECT_ID}@appspot.gserviceaccount.com \
  --role=roles/cloudfunctions.invoker