获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

使用 Cloud Tasks 将函数排入队列

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

任务队列函数利用 Google Cloud Tasks帮助您的应用在主应用流程之外异步运行耗时、资源密集或带宽受限的任务。

例如,假设您想要创建大量图像文件的备份,这些图像文件当前托管在具有速率限制的 API 上。为了成为该 API 的负责任消费者,您需要尊重他们的速率限制。此外,由于超时和内存限制,这种长时间运行的作业可能容易失败。

为了减轻这种复杂性,您可以编写一个任务队列函数来设置基本任务选项,如scheduleTimedispatchDeadline ,然后将该函数交给 Cloud Tasks 中的队列。 Cloud Tasks 环境专门设计用于确保对此类操作进行有效的拥塞控制和重试策略。

Firebase Cloud Functions for Firebase v3.20.1 及更高版本的 Firebase SDK 与 Firebase Admin SDK v10.2.0 及更高版本互操作以支持任务队列功能。

在 Firebase 中使用任务队列功能可能会产生 Cloud Tasks 处理费用。有关更多信息,请参阅Cloud Tasks 定价

创建任务队列函数

要使用任务队列功能,请遵循以下工作流程:

  1. 使用 Firebase SDK for Cloud Functions 编写任务队列函数。
  2. 使用 Firebase 本地模拟器套件测试您的功能。
  3. 使用 Firebase CLI 部署您的函数。首次部署任务队列功能时,CLI 将在 Cloud Tasks 中创建一个任务队列,并在您的源代码中指定选项(速率限制和重试)。
  4. 将任务添加到新创建的任务队列中,并在需要时传递参数以设置执行计划。您可以通过使用 Admin SDK 编写代码并将其部署到 Cloud Functions for Firebase 来实现此目的。

编写任务队列函数

使用onDispatch开始编写任务队列函数。编写任务队列函数的一个重要部分是设置每个队列的重试和限速配置。此页面中的代码示例基于一个应用程序,该应用程序设置了一项服务,该服务备份来自 NASA 的每日天文图片的所有图像:

任务队列配置

任务队列函数带有一组强大的配置设置,可以精确控制任务队列的速率限制和重试行为:

exports.backupApod = functions
    .runWith( {secrets: ["NASA_API_KEY"]})
    .tasks.taskQueue({
      retryConfig: {
        maxAttempts: 5,
        minBackoffSeconds: 60,
      },
      rateLimits: {
        maxConcurrentDispatches: 6,
      },
    }).onDispatch(async (data) => {
  • retryConfig.maxAttempts=5 :任务队列中的每个任务自动重试最多 5 次。这有助于缓解暂时性错误,例如网络错误或依赖的外部服务的临时服务中断。
  • retryConfig.minBackoffSeconds=60 :每个任务在每次尝试后至少重试 60 秒。这在每次尝试之间提供了很大的缓冲,因此我们不会急于过快地耗尽 5 次重试尝试。
  • rateLimits.maxConcurrentDispatch=6 :在给定时间最多分派 6 个任务。这有助于确保对底层函数的请求源源不断,并有助于减少活动实例和冷启动的数量。

使用 Firebase Local Emulator Suite 测试任务队列功能

Firebase Local Emulator Suite 中的任务队列函数公开为简单的 HTTP 函数。您可以通过发送带有 json 数据负载的 HTTP POST 请求来测试模拟任务功能:

 # 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 CLI 部署任务队列功能:

$ firebase deploy --only functions:backupApod

首次部署任务队列功能时,CLI 会在 Cloud Tasks 中创建一个任务队列,并在您的源代码中指定选项(速率限制和重试)。

如果您在部署函数时遇到权限错误,请确保将适当的IAM 角色分配给运行部署命令的用户。

入队函数

可以使用适用于 Node.js 的 Firebase Admin SDK 将任务队列函数从受信任的服务器环境(如 Cloud Functions for Firebase)排入 Cloud Tasks 队列。如果您不熟悉 Admin SDK,请参阅将 Firebase 添加到服务器以开始使用。

在典型流程中,Admin SDK 创建一个新任务,将其排入 {cloudtasks_name}} 队列,并为任务设置配置:

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 day. 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 分钟的延迟来分散任务的执行。这转化为触发约 1 个任务/分钟。请注意,如果您希望 Cloud Tasks 在特定时间触发任务,也可以使用scheduleTime
  • dispatchDeadlineSeconds :Cloud Tasks 等待任务完成的最长时间。 Cloud Tasks 将在队列的重试配置之后重试该任务,或者直到达到此期限。在示例中,队列被配置为重试任务最多 5 次,但如果整个过程(包括重试尝试)时间超过 5 分钟,任务将自动取消。

故障排除

打开 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 默认服务帐户用户的说明,请参阅Google Cloud IAM 文档

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