工作佇列函式可利用 Google Cloud Tasks 的優勢,在主要應用程式流程之外,以非同步方式執行耗時、耗用大量資源或頻寬受限的工作。
舉例來說,假設您想為大量圖片檔案建立備份,而這些檔案目前託管在設有速率限制的 API 上。為成為負責任的 API 使用者,您必須遵守頻率限制。此外,這類長時間執行的工作可能會因逾時和記憶體限制而發生失敗。
為降低這種複雜性,您可以編寫任務佇列函式,設定 scheduleTime
和 dispatchDeadline
等基本任務選項,然後將函式交給 Cloud Tasks 中的佇列。Cloud Tasks 環境經過特別設計,能確保這類作業的有效壅塞控管和重試政策。
Cloud Functions for Firebase v3.20.1 以上版本的 Firebase SDK 可與 Firebase Admin SDK v10.2.0 以上版本互通,支援工作佇列函式。
使用 Firebase 的任務佇列函式可能會產生 Cloud Tasks 處理費用。詳情請參閱 Cloud Tasks 定價。
建立工作佇列函式
如要使用工作佇列函式,請按照下列工作流程操作:
- 使用 Cloud Functions 適用的 Firebase SDK 編寫工作佇列函式。
- 透過 HTTP 要求觸發函式來測試函式。
- 使用 Firebase CLI 部署函式。首次部署工作佇列函式時,CLI 會在 Cloud Tasks 中建立工作佇列,並使用原始碼中指定的選項 (速率限制和重試)。
- 將工作新增至新建的工作佇列,並傳遞參數,以便視需要設定執行時程。您可以使用 Admin SDK 編寫程式碼,然後部署至 Cloud Functions for Firebase。
編寫工作佇列函式
使用 onDispatch
開始編寫工作佇列函式。編寫工作佇列函式時,重要的一環是設定個別佇列的重試和速率限制設定。本頁的程式碼範例是以應用程式為基礎,該應用程式會設定服務,用於備份 NASA Astronomy Picture of the Day 的所有圖片:
設定工作佇列函式
工作佇列功能提供一組強大的設定,可精確控制工作佇列的速率限制和重試行為:
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 項工作。這有助於確保對基礎函式的要求穩定流量,並有助於減少有效執行個體和冷啟動的數量。
測試工作佇列函式
在大多數情況下,Cloud Functions 模擬器是測試工作佇列函式的最佳方式。請參閱模擬器套件說明文件,瞭解如何檢測應用程式以模擬工作佇列函式。
此外,工作佇列函式會在 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 會建立新工作,在 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 中的記錄會包含實用的診斷資訊,例如與工作相關聯的要求狀態。由於 Cloud Tasks 可能會在您的專案上產生大量記錄,因此預設情況下會關閉來自 Cloud Tasks 的記錄。建議您在積極開發及偵錯工作佇列函式時,開啟偵錯記錄。請參閱「開啟記錄功能」。
身分與存取權管理權限
排入工作佇列時,或 Cloud Tasks 嘗試叫用工作佇列函式時,您可能會看到 PERMISSION DENIED
錯誤。請確認專案具有下列身分與存取權管理繫結:
用於將工作排入 Cloud Tasks 佇列的身分需要
cloudtasks.tasks.create
IAM 權限。在本範例中,這是 App Engine 的預設服務帳戶
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 說明文件。
用於觸發工作佇列函式的身分必須具備
cloudfunctions.functions.invoke
權限。在範例中,這是 App Engine 預設服務帳戶。
gcloud functions add-iam-policy-binding $FUNCTION_NAME \
--region=us-central1 \
--member=serviceAccount:${PROJECT_ID}@appspot.gserviceaccount.com \
--role=roles/cloudfunctions.invoker