Cloud Tasks ile işlevleri sıraya alma

Görev sırası işlevleri, uygulamanızın zaman alan, yoğun kaynak kullanan veya bant genişliği sınırlı görevleri ana uygulama akışınızın dışında eşzamansız olarak çalıştırmasına yardımcı olmak için Google Cloud Tasks'dan yararlanır.

Örneğin, şu anda sıklık sınırlaması olan bir API'de barındırılan büyük bir resim dosyası grubunun yedeklerini oluşturmak istediğinizi varsayalım. Bu API'nin sorumlu bir tüketicisi olmak için sıklık sınırlamalarına uymanız gerekir. Ayrıca bu tür uzun süreli işler, zaman aşımı ve bellek sınırları nedeniyle başarısız olabilir.

Bu karmaşıklığı azaltmak için scheduleTime ve dispatchDeadline gibi temel görev seçeneklerini ayarlayan bir görev sırası işlevi yazabilir ve ardından işlevi Cloud Tasks içindeki bir sıraya aktarabilirsiniz. Cloud Tasks ortamı, bu tür işlemler için etkili tıkanıklık kontrolü ve yeniden deneme politikaları sağlamak üzere özel olarak tasarlanmıştır.

Cloud Functions for Firebase için Firebase SDK'sı 3.20.1 ve sonraki sürümler, görev sırası işlevlerini desteklemek için Firebase Admin SDK 10.2.0 ve sonraki sürümlerle birlikte çalışır.

Görev sırası işlevlerini Firebase ile kullanmak, Cloud Tasks işleme ücretlerine neden olabilir. Daha fazla bilgi için Cloud Tasks fiyatlandırması sayfasına bakın.

Görev sırası işlevleri oluşturma

Görev sırası işlevlerini kullanmak için aşağıdaki iş akışını uygulayın:

  1. Cloud Functions için Firebase SDK'sını kullanarak bir görev sırası işlevi yazın.
  2. İşlevinizi bir HTTP isteğiyle tetikleyerek test edin.
  3. İşlevinizi Firebase KSA ile dağıtın. Görev sırası işlevinizi ilk kez dağıtırken KSA, kaynak kodunuzda belirtilen seçeneklerle (sıklık sınırlaması ve yeniden deneme) Cloud Tasks içinde bir görev sırası oluşturur.
  4. Yeni oluşturulan görev sırasına görevler ekleyin ve gerekirse çalıştırma zamanı ayarlamak için parametreleri iletin. Bunun için Admin SDK kullanarak kodu yazabilir ve Cloud Functions for Firebase platformuna dağıtabilirsiniz.

Görev sırası işlevleri yazma

Bu bölümdeki kod örnekleri, NASA'nın Günün Astronomi Resmi'ndeki tüm resimleri yedekleyen bir hizmet oluşturan uygulamayı temel alır. Başlamak için gerekli modülleri içe aktarın:

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

Görev sırası işlevleri için onTaskDispatched veya on_task_dispatched kullanın. Görev sırası işlevi yazarken sıra başına yeniden deneme ve sıklık sınırlaması yapılandırması belirleyebilirsiniz.

Görev sırası işlevlerini yapılandırma

Görev sırası işlevleri, bir görev sırasının sıklık sınırlarını ve yeniden deneme davranışını hassas bir şekilde kontrol etmek için güçlü bir yapılandırma ayarları setiyle birlikte sunulur:

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: Görev sırasındaki her görev otomatik olarak en fazla 5 kez yeniden denenir. Bu sayede, ağ hataları veya bağımlı bir harici hizmetin geçici olarak kesintiye uğraması gibi geçici hatalar azaltılır.

  • retryConfig.minBackoffSeconds=60: Her görev, her denemeden en az 60 saniye sonra yeniden denenir. Bu sayede her deneme arasında uzun bir süre olur ve 5 yeniden deneme hakkını çok hızlı bir şekilde tüketmeyiz.

  • rateLimits.maxConcurrentDispatch=6: Belirli bir zamanda en fazla 6 görev gönderilir. Bu, temel işleve sürekli bir istek akışı olmasını sağlar ve etkin örneklerin ve baştan başlatmaların sayısını azaltmaya yardımcı olur.

Görev sırası işlevlerini test etme

Çoğu durumda, görev sırası işlevlerini test etmenin en iyi yolu Cloud Functions emülatörüdür. Uygulamanızı görev sırası işlevleri emülasyonu için nasıl hazırlayacağınızı öğrenmek üzere Emulator Suite belgelerine bakın.

Ayrıca, görev sırası işlevleri Firebase Local Emulator Suite içinde basit HTTP işlevleri olarak gösterilir. JSON veri yükü içeren bir HTTP POST isteği göndererek öykünülen bir görev işlevini test edebilirsiniz:

 # 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

Görev sırası işlevlerini dağıtma

Firebase KSA'yı kullanarak görev sırası işlevini dağıtın:

$ firebase deploy --only functions:backupapod

Bir görev sırası işlevini ilk kez dağıtırken KSA, kaynak kodunuzda belirtilen seçeneklerle (sıklık sınırlaması ve yeniden deneme) Cloud Tasks içinde bir görev sırası oluşturur.

İşlevleri dağıtırken izin hatalarıyla karşılaşırsanız dağıtım komutlarını çalıştıran kullanıcıya uygun IAM rollerinin atandığından emin olun.

Görev sırası işlevlerini sıraya alma

Görev sırası işlevleri, Node.js için Firebase Admin SDK veya Python için Google Cloud kitaplıkları kullanılarak Cloud Functions for Firebase gibi güvenilir bir sunucu ortamından Cloud Tasks içinde sıraya alınabilir. Admin SDK kullanmaya yeni başladıysanız başlamak için Firebase'i bir sunucuya ekleme başlıklı makaleyi inceleyin.

Tipik bir akış, yeni bir görev oluşturur, görevi Cloud Tasks içinde sıraya alır ve görevin yapılandırmasını ayarlar:

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")
  • Örnek kod, N. görev için N. dakikalık bir gecikme ilişkilendirerek görevlerin yürütülmesini yaymaya çalışır. Bu, dakikada yaklaşık 1 görevin tetiklendiği anlamına gelir. Bir görevi belirli bir zamanda tetiklemek istiyorsanız scheduleTime (Node.js) veya schedule_time (Python) da kullanabilirsiniz.Cloud Tasks

  • Örnek kod, Cloud Tasks hizmetinin bir görevin tamamlanması için bekleyeceği maksimum süreyi ayarlar. Cloud Tasks, sıranın yeniden deneme yapılandırmasına göre veya bu son tarihe ulaşılana kadar görevi yeniden dener. Örnekte, sıra görevi en fazla 5 kez yeniden deneyecek şekilde yapılandırılmıştır ancak tüm işlem (yeniden deneme girişimleri dahil) 5 dakikadan uzun sürerse görev otomatik olarak iptal edilir.

Sorun giderme

Günlük kaydı kullanarak görev sıralarıyla ilgili sorunları nasıl teşhis edeceğinizi ve gerekli IAM izinlerini nasıl yapılandıracağınızı öğrenin.

Cloud Tasks günlük kaydını etkinleştirme

Cloud Tasks günlükleri, bir görevle ilişkili isteğin durumu gibi faydalı teşhis bilgileri içerir. Projenizde oluşturabileceği büyük hacimli günlükler nedeniyle Cloud Tasks günlükleri varsayılan olarak devre dışıdır. Görev sırası işlevlerinizi aktif olarak geliştirirken ve hatalarını ayıklarken hata ayıklama günlüklerini etkinleştirmenizi öneririz. Günlük kaydını etkinleştirme başlıklı makaleyi inceleyin.

IAM İzinleri

Görevleri sıraya eklerken veya Cloud Tasks, görev sırası işlevlerinizi çağırmaya çalışırken PERMISSION DENIED hataları görebilirsiniz. Projenizin aşağıdaki IAM bağlamalarına sahip olduğundan emin olun:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member=serviceAccount:${PROJECT_ID}@appspot.gserviceaccount.com \
  --role=roles/cloudtasks.enqueuer
  • Cloud Tasks için görevleri sıraya almak üzere kullanılan kimliğin, Cloud Tasks içindeki bir görevle ilişkili hizmet hesabını kullanma iznine sahip olması gerekir.

    Örnekte bu, App Engine varsayılan hizmet hesabıdır.

App Engine varsayılan hizmet hesabını, App Engine varsayılan hizmet hesabının kullanıcısı olarak ekleme talimatları için Google Cloud IAM belgelerine bakın.

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