使用 Cloud Tasks 將函數排入隊列


任務佇列函數利用 Google Cloud Tasks來協助您的應用程式在主應用程式流程之外非同步運行耗時、資源密集或頻寬有限的任務。

例如,假設您想要建立目前託管在具有速率限制的 API 上的大量映像檔的備份。為了成為該 API 的負責任的消費者,您需要尊重他們的速率限制。另外,這種長時間運行的作業可能容易因逾時和記憶體限製而失敗。

為了減輕這種複雜性,您可以編寫一個任務佇列函數來設定基本任務選項,例如scheduleTimedispatchDeadline ,然後將函數交給 Cloud Tasks 中的佇列。 Cloud Tasks 環境專門設計用於確保此類操作的有效擁塞控制和重試策略。

Firebase SDK for Cloud Functions for Firebase v3.20.1 及更高版本可與 Firebase Admin SDK v10.2.0 及更高版本互通,以支援任務佇列功能。

將任務佇列函數與 Firebase 結合使用可能會產生 Cloud Tasks 處理費用。有關更多信息,請參閱雲任務定價

建立任務隊列函數

若要使用任務佇列功能,請遵循以下工作流程:

  1. 使用 Firebase SDK for Cloud Functions 編寫任務佇列函數。
  2. 透過使用 HTTP 請求觸發函數來測試您的函數。
  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 本機模擬器套件中的任務佇列函數公開為簡單的 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 角色指派給執行部署命令的使用者。

Enqueue任務佇列函數

可以使用適用於 Node.js 的 Firebase Admin SDK 從受信任的伺服器環境(例如 Cloud Functions for Firebase)將任務佇列函數排入 Cloud Tasks 中。如果您不熟悉 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 分鐘的延遲來分散任務的執行。這意味著每分鐘觸發約 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 預設服務帳戶

請參閱Google Cloud IAM 文檔,以了解有關如何將 App Engine 預設服務帳戶新增為 App Engine 預設服務帳戶的使用者的說明。

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