تستفيد دوال قائمة انتظار المهام من Google Cloud Tasks لمساعدة تطبيقك في تنفيذ المهام التي تستغرق وقتًا طويلاً أو تستهلك الكثير من الموارد أو ذات النطاق الترددي المحدود بشكل غير متزامن، خارج مسار التطبيق الرئيسي.
على سبيل المثال، لنفترض أنّك تريد إنشاء نُسخ احتياطية من مجموعة كبيرة من ملفات الصور المستضافة حاليًا على واجهة برمجة تطبيقات ذات حدّ أقصى لمعدّل نقل البيانات. لكي تكون مستهلكًا مسؤولاً لواجهة برمجة التطبيقات هذه، عليك احترام حدود المعدلات. بالإضافة إلى ذلك، قد تكون هذه الأنواع من المهام الطويلة عرضة للفشل بسبب انتهاء المهلة وحدود الذاكرة.
لتقليل هذا التعقيد، يمكنك كتابة دالة قائمة انتظار مهام تضبط خيارات المهام الأساسية، مثل scheduleTime وdispatchDeadline، ثم تسلّم الدالة إلى قائمة انتظار في Cloud Tasks. تم تصميم بيئة Cloud Tasks خصيصًا لضمان التحكّم الفعّال في الازدحام وسياسات إعادة المحاولة لهذه الأنواع من العمليات.
تتوافق حزمة Firebase SDK للإصدار 3.20.1 من Cloud Functions for Firebase والإصدارات الأحدث مع الإصدار 10.2.0 من Firebase Admin SDK والإصدارات الأحدث لإتاحة وظائف قائمة انتظار المهام.
قد يؤدي استخدام دوال قائمة انتظار المهام مع Firebase إلى فرض رسوم على معالجة Cloud Tasks. لمزيد من المعلومات، يُرجى الاطّلاع على أسعار Cloud Tasks.
إنشاء دوال قائمة انتظار المهام
لاستخدام دوال قائمة انتظار المهام، اتّبِع سير العمل التالي:
- اكتب دالة قائمة انتظار المهام باستخدام حزمة تطوير البرامج (SDK) لـ Firebase في Cloud Functions.
- اختبِر الدالة من خلال تشغيلها باستخدام طلب HTTP.
- انشر الدالة باستخدام واجهة سطر الأوامر (CLI) في Firebase. عند نشر دالة قائمة انتظار المهام لأول مرة، ستنشئ واجهة سطر الأوامر قائمة انتظار مهام في Cloud Tasks مع الخيارات (تحديد المعدّل وإعادة المحاولة) المحدّدة في الرمز المصدر.
- أضِف مهامًا إلى قائمة انتظار المهام التي تم إنشاؤها حديثًا، مع تمرير المَعلمات لإعداد جدول تنفيذ إذا لزم الأمر. يمكنك تحقيق ذلك من خلال كتابة الرمز باستخدام Admin SDK ونشره على Cloud Functions for Firebase.
كتابة دوال قائمة انتظار المهام
تستند عيّنات التعليمات البرمجية في هذا القسم إلى تطبيق يُعدّ خدمة للاحتفاظ بنسخة احتياطية من جميع الصور من صورة اليوم الفلكية من وكالة ناسا. للبدء، استورِد الوحدات المطلوبة:
Node.js
// Dependencies for task queue functions.
const {onTaskDispatched} = require("firebase-functions/tasks");
const {onRequest, HttpsError} = require("firebase-functions/https");
const {requiresRole} = require("firebase-functions");
const {getFunctions} = require("firebase-admin/functions");
const {logger} = require("firebase-functions");
// Dependencies for image backup.
const {URL, URLSearchParams} = require("node:url");
const path = require("path");
const {initializeApp} = require("firebase-admin/app");
const {getStorage} = require("firebase-admin/storage");
Python
# 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
لدوال قائمة انتظار المهام. عند كتابة دالة قائمة انتظار المهام،
يمكنك ضبط إعدادات إعادة المحاولة وتحديد المعدّل لكل قائمة انتظار.
ضبط دوال قائمة انتظار المهام
تتوفّر دوال قائمة انتظار المهام مع مجموعة فعّالة من إعدادات الضبط للتحكّم بدقة في حدود المعدّل وسلوك إعادة المحاولة لقائمة انتظار المهام:
Node.js
exports.backupapod = onTaskDispatched(
{
retryConfig: {
maxAttempts: 5,
minBackoffSeconds: 60,
},
rateLimits: {
maxConcurrentDispatches: 6,
},
}, async (req) => {
Python
@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: تتم إعادة محاولة تنفيذ كل مهمة بعد مرور 60 ثانية على الأقل من كل محاولة. يوفّر ذلك فترة انتظار طويلة بين كل محاولة كي لا نستنفد محاولات إعادة المحاولة الخمس بسرعة كبيرة.rateLimits.maxConcurrentDispatch=6: يتم إرسال 6 مهام كحد أقصى في وقت معيّن. يساعد ذلك في ضمان تدفق مستمر للطلبات إلى الدالة الأساسية ويساعد في تقليل عدد المثيلات النشطة وعمليات التشغيل على البارد.
اختبار دوال قائمة انتظار المهام
في معظم الحالات، يُعدّ محاكي Cloud Functions أفضل طريقة لاختبار وظائف قائمة انتظار المهام. يمكنك الاطّلاع على مستندات "مجموعة أدوات المحاكاة" للتعرّف على كيفية إعداد تطبيقك لمحاكاة دوال قائمة انتظار المهام.
بالإضافة إلى ذلك، يتم عرض دوال قائمة انتظار المهام كدوال 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 مع الخيارات (تحديد المعدّل وإعادة المحاولة) المحدّدة في الرمز المصدر.
إذا واجهت أخطاء في الأذونات عند نشر الدوال، تأكَّد من أنّ أدوار إدارة الهوية وإمكانية الوصول المناسبة تم إسنادها إلى المستخدم الذي يشغّل أوامر النشر.
إضافة دوال قائمة انتظار المهام إلى قائمة الانتظار
يمكن إضافة دوال قائمة انتظار المهام إلى قائمة الانتظار في Cloud Tasks من بيئة خادم موثوقة مثل Cloud Functions for Firebase باستخدام Firebase Admin SDK لـ Node.js أو مكتبات Google Cloud لـ Python. إذا كنت مستخدمًا جديدًا لـ Admin SDK، يُرجى الاطّلاع على مقالة إضافة Firebase إلى خادم للبدء.
ينشئ المسار المعتاد مهمة جديدة، ويضعها في قائمة الانتظار في Cloud Tasks، ويضبط إعدادات المهمة:
Node.js
exports.enqueuebackuptasks = onRequest(
async (_request, response) => {
const queue = getFunctions().taskQueue("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
}),
);
}
await Promise.all(enqueues);
response.sendStatus(200);
});
Python
@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. وهذا يعني تشغيل مهمة واحدة تقريبًا في الدقيقة. يمكنك أيضًا استخدام
scheduleTime(Node.js) أوschedule_time(Python) إذا أردت أن يشغّل Cloud Tasks مهمة في وقت محدّد.يحدّد الرمز النموذجي الحد الأقصى للوقت الذي سينتظره "Cloud Tasks" لإكمال مهمة معيّنة. ستعيد خدمة "Cloud Tasks" محاولة تنفيذ المهمة وفقًا لإعدادات إعادة المحاولة في قائمة الانتظار أو إلى أن يتم بلوغ هذا الموعد النهائي. في النموذج، تم ضبط قائمة الانتظار لإعادة محاولة تنفيذ المهمة حتى 5 مرات، ولكن يتم إلغاء المهمة تلقائيًا إذا استغرقت العملية بأكملها (بما في ذلك محاولات إعادة المحاولة) أكثر من 5 دقائق.
تحديد المشاكل وحلّها
تعرَّف على كيفية تشخيص المشاكل في قوائم انتظار المهام باستخدام التسجيل وضبط أذونات "إدارة الهوية وإمكانية الوصول" المطلوبة.
تفعيل تسجيل Cloud Tasks
تحتوي السجلّات من Cloud Tasks على معلومات تشخيصية مفيدة، مثل حالة الطلب المرتبط بمهمة. تكون السجلّات من Cloud Tasks غير مفعَّلة تلقائيًا بسبب العدد الكبير من السجلّات التي يمكن إنشاؤها في مشروعك. ننصحك بتفعيل سجلّات تصحيح الأخطاء أثناء تطوير دوال قائمة انتظار المهام وتصحيح أخطائها بشكل نشط. يُرجى الاطّلاع على تفعيل التسجيل.
أذونات "إدارة الهوية وإمكانية الوصول"
قد تظهر لك أخطاء PERMISSION DENIED عند إضافة المهام إلى قائمة الانتظار أو عندما تحاول Cloud Tasks استدعاء دوال قائمة انتظار المهام. تأكَّد من أنّ مشروعك يتضمّن عمليات الربط التالية في "إدارة الهوية وإمكانية الوصول":
تحتاج الهوية المستخدَمة لإضافة المهام إلى قائمة الانتظار في 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.
يمكنك الاطّلاع على مستندات Google Cloud IAM للحصول على تعليمات حول كيفية إضافة حساب الخدمة التلقائي "App Engine" كمستخدم لحساب الخدمة التلقائي "App Engine".
يجب أن تحصل الهوية المستخدَمة لتشغيل دالة قائمة انتظار المهام على إذن
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