توابع صف وظایف از Google Cloud Tasks بهره میبرند تا به برنامه شما کمک کنند وظایف زمانبر، منابعبر یا با محدودیت پهنای باند را به صورت غیرهمزمان و خارج از جریان اصلی برنامه شما اجرا کند.
برای مثال، تصور کنید که میخواهید از مجموعه بزرگی از فایلهای تصویری که در حال حاضر روی یک API با محدودیت سرعت میزبانی میشوند، پشتیبان تهیه کنید. برای اینکه مصرفکننده مسئولی برای آن API باشید، باید محدودیتهای سرعت آنها را رعایت کنید. به علاوه، این نوع کار طولانی مدت میتواند به دلیل وقفههای زمانی و محدودیتهای حافظه در معرض شکست باشد.
برای کاهش این پیچیدگی، میتوانید یک تابع صف وظیفه بنویسید که گزینههای اساسی وظیفه مانند scheduleTime
و dispatchDeadline
را تنظیم کند و سپس تابع را به یک صف در Cloud Tasks واگذار کند. محیط Cloud Tasks به طور خاص برای اطمینان از کنترل ازدحام موثر و سیاستهای تلاش مجدد برای این نوع عملیات طراحی شده است.
کیت توسعه نرمافزار Firebase برای Cloud Functions for Firebase نسخه ۳.۲۰.۱ و بالاتر با Firebase Admin SDK ۱۰.۲.۰ و بالاتر برای پشتیبانی از توابع صف وظایف، تعامل دارد.
استفاده از توابع صف وظایف با Firebase میتواند منجر به هزینههایی برای پردازش Cloud Tasks شود. برای اطلاعات بیشتر به قیمتگذاری Cloud Tasks مراجعه کنید.
ایجاد توابع صف وظایف
برای استفاده از توابع صف وظایف، این گردش کار را دنبال کنید:
- با استفاده از Firebase SDK for Cloud Functions یک تابع صف وظایف بنویسید.
- تابع خود را با اجرای آن با یک درخواست HTTP آزمایش کنید.
- تابع خود را با استفاده از رابط خط فرمان Firebase CLI) مستقر کنید. هنگام استقرار تابع صف وظایف خود برای اولین بار، رابط خط فرمان (CLI) یک صف وظایف در Cloud Tasks با گزینههایی (محدود کردن سرعت و تلاش مجدد) که در کد منبع شما مشخص شدهاند، ایجاد میکند.
- وظایف را به صف وظایف تازه ایجاد شده اضافه کنید و در صورت نیاز پارامترهایی را برای تنظیم برنامه اجرا ارسال کنید. میتوانید با نوشتن کد با استفاده از Admin SDK و استقرار آن در Cloud Functions for Firebase به این هدف دست یابید.
نوشتن توابع صف وظایف
نمونههای کد در این بخش بر اساس برنامهای هستند که سرویسی را راهاندازی میکند که از تمام تصاویر «تصویر نجومی روز ناسا» پشتیبانگیری میکند. برای شروع، ماژولهای مورد نیاز را وارد کنید:
نود جی اس
// Dependencies for task queue functions.
const {onTaskDispatched} = require("firebase-functions/tasks");
const {onRequest, HttpsError} = require("firebase-functions/https");
const {getFunctions} = require("firebase-admin/functions");
const {logger} = require("firebase-functions");
// Dependencies for image backup.
const path = require("path");
const {initializeApp} = require("firebase-admin/app");
const {getStorage} = require("firebase-admin/storage");
const {GoogleAuth} = require("google-auth-library");
پایتون
# Dependencies for task queue functions.
from google.cloud import tasks_v2
import requests
from firebase_functions.options import RetryConfig, RateLimits, SupportedRegion
# Dependencies for image backup.
from datetime import datetime, timedelta
import json
import pathlib
from urllib.parse import urlparse
from firebase_admin import initialize_app, storage, functions
from firebase_functions import https_fn, tasks_fn, params
import google.auth
from google.auth.transport.requests import AuthorizedSession
برای توابع صف وظایف onTaskDispatched
یا on_task_dispatched
استفاده کنید. هنگام نوشتن یک تابع صف وظایف، میتوانید پیکربندی تلاش مجدد به ازای هر صف و محدود کردن سرعت را تنظیم کنید.
پیکربندی توابع صف وظایف
توابع صف وظیفه با مجموعهای قدرتمند از تنظیمات پیکربندی ارائه میشوند تا محدودیتهای نرخ و رفتار تلاش مجدد صف وظیفه را به طور دقیق کنترل کنند:
نود جی اس
exports.backupapod = onTaskDispatched(
{
retryConfig: {
maxAttempts: 5,
minBackoffSeconds: 60,
},
rateLimits: {
maxConcurrentDispatches: 6,
},
}, async (req) => {
پایتون
@tasks_fn.on_task_dispatched(retry_config=RetryConfig(max_attempts=5, min_backoff_seconds=60),
rate_limits=RateLimits(max_concurrent_dispatches=10))
def backupapod(req: tasks_fn.CallableRequest) -> str:
"""Grabs Astronomy Photo of the Day (APOD) using NASA's API."""
retryConfig.maxAttempts=5
: هر وظیفه در صف وظایف به طور خودکار تا 5 بار دوباره امتحان میشود. این به کاهش خطاهای گذرا مانند خطاهای شبکه یا اختلال موقت سرویس یک سرویس خارجی وابسته کمک میکند.retryConfig.minBackoffSeconds=60
: هر وظیفه حداقل با فاصله ۶۰ ثانیه از هر تلاش دوباره اجرا میشود. این یک بافر بزرگ بین هر تلاش فراهم میکند، بنابراین ما عجله نمیکنیم که ۵ تلاش دوباره را خیلی سریع تمام کنیم.rateLimits.maxConcurrentDispatch=6
: حداکثر ۶ وظیفه در یک زمان معین ارسال میشوند. این به تضمین جریان ثابتی از درخواستها به تابع اصلی کمک میکند و به کاهش تعداد نمونههای فعال و شروعهای سرد کمک میکند.
توابع صف وظیفه را آزمایش کنید
در بیشتر موارد، شبیهساز Cloud Functions بهترین روش برای آزمایش توابع صف وظایف است. برای یادگیری نحوهی تجهیز برنامهی خود برای شبیهسازی توابع صف وظایف، به مستندات Emulator Suite مراجعه کنید.
علاوه بر این، توابع صف وظایف به عنوان توابع ساده HTTP در Firebase Local Emulator Suite ارائه میشوند. میتوانید یک تابع وظیفه شبیهسازی شده را با ارسال یک درخواست HTTP POST با یک داده JSON آزمایش کنید:
# start the Local Emulator Suite
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 Functions for Firebase با استفاده از Firebase Admin SDK برای Node.js یا کتابخانههای گوگل کلود برای پایتون، در Cloud Tasks صفبندی کرد. اگر در استفاده از Admin SDK تازهکار هستید، برای شروع به بخش افزودن فایربیس به سرور مراجعه کنید.
یک جریان معمول، یک وظیفه جدید ایجاد میکند، آن را در Cloud Tasks قرار میدهد و پیکربندی وظیفه را تنظیم میکند:
نود جی اس
exports.enqueuebackuptasks = onRequest(
async (_request, response) => {
const queue = getFunctions().taskQueue("backupapod");
const targetUri = await getFunctionUrl("backupapod");
const enqueues = [];
for (let i = 0; i <= BACKUP_COUNT; i += 1) {
const iteration = Math.floor(i / HOURLY_BATCH_SIZE);
// Delay each batch by N * hour
const scheduleDelaySeconds = iteration * (60 * 60);
const backupDate = new Date(BACKUP_START_DATE);
backupDate.setDate(BACKUP_START_DATE.getDate() + i);
// Extract just the date portion (YYYY-MM-DD) as string.
const date = backupDate.toISOString().substring(0, 10);
enqueues.push(
queue.enqueue({date}, {
scheduleDelaySeconds,
dispatchDeadlineSeconds: 60 * 5, // 5 minutes
uri: targetUri,
}),
);
}
await Promise.all(enqueues);
response.sendStatus(200);
});
پایتون
@https_fn.on_request()
def enqueuebackuptasks(_: https_fn.Request) -> https_fn.Response:
"""Adds backup tasks to a Cloud Tasks queue."""
task_queue = functions.task_queue("backupapod")
target_uri = get_function_url("backupapod")
for i in range(BACKUP_COUNT):
batch = i // HOURLY_BATCH_SIZE
# Delay each batch by N hours
schedule_delay = timedelta(hours=batch)
schedule_time = datetime.now() + schedule_delay
dispatch_deadline_seconds = 60 * 5 # 5 minutes
backup_date = BACKUP_START_DATE + timedelta(days=i)
body = {"data": {"date": backup_date.isoformat()[:10]}}
task_options = functions.TaskOptions(schedule_time=schedule_time,
dispatch_deadline_seconds=dispatch_deadline_seconds,
uri=target_uri)
task_queue.enqueue(body, task_options)
return https_fn.Response(status=200, response=f"Enqueued {BACKUP_COUNT} tasks")
کد نمونه سعی میکند با اختصاص تأخیر N دقیقهای برای Nمین وظیفه، اجرای وظایف را گسترش دهد. این به معنای راهاندازی حدود ۱ وظیفه در دقیقه است. توجه داشته باشید که اگر میخواهید Cloud Tasks یک وظیفه را در زمان خاصی راهاندازی کند، میتوانید از
scheduleTime
(Node.js) یاschedule_time
(Python) نیز استفاده کنید.کد نمونه حداکثر مدت زمانی را که Cloud Tasks برای تکمیل یک وظیفه منتظر میماند، تعیین میکند. Cloud Tasks پس از پیکربندی تلاش مجدد صف یا تا زمان رسیدن به این مهلت، وظیفه را دوباره امتحان میکند. در نمونه، صف طوری پیکربندی شده است که وظیفه را تا 5 بار دوباره امتحان کند، اما اگر کل فرآیند (شامل تلاشهای تلاش مجدد) بیش از 5 دقیقه طول بکشد، وظیفه به طور خودکار لغو میشود.
عیبیابی
فعال کردن ثبت Cloud Tasks
گزارشهای Cloud Tasks حاوی اطلاعات تشخیصی مفیدی مانند وضعیت درخواست مرتبط با یک وظیفه هستند. به طور پیشفرض، گزارشهای Cloud Tasks به دلیل حجم زیاد گزارشهایی که میتواند به طور بالقوه در پروژه شما ایجاد کند، غیرفعال هستند. توصیه میکنیم در حالی که به طور فعال در حال توسعه و اشکالزدایی توابع صف وظایف خود هستید، گزارشهای اشکالزدایی را فعال کنید. به بخش فعال کردن گزارشگیری مراجعه کنید.
مجوزهای IAM
ممکن است هنگام قرار دادن وظایف در صف یا زمانی که Cloud Tasks سعی میکند توابع صف وظایف شما را فراخوانی کند، با خطای PERMISSION DENIED
مواجه شوید. مطمئن شوید که پروژه شما دارای اتصالات IAM زیر است:
هویتی که برای قرار دادن وظایف در Cloud Tasks استفاده میشود، به مجوز IAM مربوط
cloudtasks.tasks.create
نیاز دارد.در نمونه، این حساب سرویس پیشفرض 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