Cloud Tasks की मदद से फ़ंक्शन को सूची में जोड़ें


टास्क की सूची वाले फ़ंक्शन, Google Cloud Tasks की सुविधा का इस्तेमाल करते हैं. इससे ऐप्लिकेशन के मुख्य फ़्लो के बाहर, एसिंक्रोनस तरीके से ज़्यादा समय लेने वाले, ज़्यादा संसाधन वाले या सीमित बैंडविथ वाले काम करने में मदद मिलती है.

उदाहरण के लिए, मान लें कि आपको इमेज फ़ाइलों के एक बड़े सेट का बैकअप लेना है जो फ़िलहाल तय सीमा वाले एपीआई पर होस्ट किया गया है. इस एपीआई का इस्तेमाल करने के लिए, आपको उसकी रेट की सीमाओं का सम्मान करना होगा. साथ ही, टाइम आउट और मेमोरी की सीमाओं की वजह से, लंबे समय तक चलने वाले इस काम के फ़ेल होने का जोखिम हो सकता है.

इस जटिलता को कम करने के लिए, आप टास्क सूची वाला फ़ंक्शन लिख सकते हैं जो scheduleTime और dispatchDeadline जैसे बुनियादी टास्क के विकल्प सेट करता है. इसके बाद, फ़ंक्शन को क्लाउड टास्क में मौजूद सूची में डाल देता है. Cloud Tasks एनवायरमेंट को खास तौर पर डिज़ाइन किया गया है, ताकि इस तरह की कार्रवाइयों के लिए, भीड़ को कंट्रोल करने और फिर से लागू करने की नीतियों को पक्का किया जा सके.

टास्क सूची के फ़ंक्शन के साथ काम करने के लिए, 'Firebase के लिए Cloud Functions' के लिए Firebase SDK टूल v3.20.1 और इसके बाद के वर्शन, Firebase एडमिन SDK v10.2.0 और इसके बाद के वर्शन के साथ काम करते हैं.

Firebase के साथ टास्क सूची वाले फ़ंक्शन का इस्तेमाल करने पर, Cloud Tasks प्रोसेसिंग के लिए शुल्क देना पड़ सकता है. ज़्यादा जानकारी के लिए, Cloud Tasks की कीमतें देखें.

टास्क सूची के फ़ंक्शन बनाना

टास्क सूची के फ़ंक्शन का इस्तेमाल करने के लिए, यह वर्कफ़्लो अपनाएं:

  1. Cloud Functions के लिए Firebase SDK टूल का इस्तेमाल करके, टास्क की सूची वाला फ़ंक्शन लिखें.
  2. अपने फ़ंक्शन को एचटीटीपी अनुरोध से ट्रिगर करके टेस्ट करें.
  3. अपने फ़ंक्शन को Firebase सीएलआई के साथ डिप्लॉय करें. टास्क की सूची वाले फ़ंक्शन को पहली बार डिप्लॉय करते समय, सीएलआई आपके सोर्स कोड में दिए गए विकल्पों (रेट सीमित करना और फिर से कोशिश करना) के साथ क्लाउड टास्क में एक टास्क सूची बनाएगा.
  4. नई बनाई गई टास्क की सूची में टास्क जोड़ें. साथ ही, ज़रूरत पड़ने पर एक्ज़ीक्यूशन शेड्यूल सेट अप करने के लिए पैरामीटर पास करें. ऐसा करने के लिए, 'एडमिन SDK' का इस्तेमाल करके कोड लिखें और उसे 'Firebase के लिए Cloud Functions' में डिप्लॉय करें.

टास्क सूची के फ़ंक्शन लिखें

इस सेक्शन में दिए गए कोड सैंपल, एक ऐसे ऐप्लिकेशन पर आधारित हैं जो एक ऐसी सेवा सेट अप करता है जो नासा के खगोल विज्ञान चित्र से ली गई सभी इमेज का बैक अप लेती है. शुरू करने के लिए, ज़रूरी मॉड्यूल इंपोर्ट करें:

Node.js के लिए

// Dependencies for task queue functions.
const {onTaskDispatched} = require("firebase-functions/v2/tasks");
const {onRequest, HttpsError} = require("firebase-functions/v2/https");
const {getFunctions} = require("firebase-admin/functions");
const {logger} = require("firebase-functions/v2");

// Dependencies for image backup.
const path = require("path");
const fetch = require("node-fetch");
const {initializeApp} = require("firebase-admin/app");
const {getStorage} = require("firebase-admin/storage");
const {GoogleAuth} = require("google-auth-library");

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: टास्क की सूची में शामिल हर टास्क को ज़्यादा से ज़्यादा पांच बार तक अपने-आप आज़माकर देखा जा सकता है. इससे नेटवर्क की गड़बड़ियों या किसी डिपेंडेंट सेवा की सेवा में कुछ समय के लिए रुकावट डालने जैसी अस्थायी गड़बड़ियों को कम करने में मदद मिलती है.

  • retryConfig.minBackoffSeconds=60: हर बार कोशिश करने के बाद, हर टास्क को कम से कम 60 सेकंड के लिए किया जाता है. इससे हर बार कोशिश करने के बीच में काफ़ी बफ़र रहना पड़ता है, इसलिए हम दोबारा कोशिश करने के पांच बार कोशिश करने को जल्द खत्म नहीं करते हैं.

  • rateLimits.maxConcurrentDispatch=6: एक समय पर ज़्यादा से ज़्यादा छह टास्क भेजे जाते हैं. इससे, मौजूदा फ़ंक्शन के लिए अनुरोधों की प्रोसेस को एक जैसा बनाए रखने में मदद मिलती है. साथ ही, ऐक्टिव इंस्टेंस और कोल्ड स्टार्ट की संख्या को कम करने में भी मदद मिलती है.

टास्क सूची के फ़ंक्शन की जांच करें

Firebase लोकल एम्युलेटर सुइट में टास्क सूची के फ़ंक्शन, सामान्य एचटीटीपी फ़ंक्शन के तौर पर दिखाए जाते हैं. 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

टास्क सूची वाले फ़ंक्शन को पहली बार डिप्लॉय करते समय, सीएलआई आपके सोर्स कोड में दिए गए विकल्पों (रेट सीमित करना और फिर से कोशिश करना) के साथ Cloud Tasks में टास्क की एक सूची बनाता है.

अगर फ़ंक्शन को डिप्लॉय करते समय अनुमतियों से जुड़ी गड़बड़ियां होती हैं, तो पक्का करें कि डिप्लॉयमेंट के निर्देश चलाने वाले उपयोगकर्ता को सही IAM भूमिकाएं असाइन की गई हों.

टास्क सूची से जुड़े फ़ंक्शन को सूची में जोड़ें

Node.js के लिए Firebase एडमिन SDK या Python के लिए Google Cloud लाइब्रेरी का इस्तेमाल करके, Firebase के लिए Cloud Functions जैसे भरोसेमंद सर्वर एनवायरमेंट से क्लाउड टास्क में टास्क की सूची वाले फ़ंक्शन जोड़े जा सकते हैं. अगर आपने एडमिन SDK टूल का इस्तेमाल पहले कभी नहीं किया है, तो शुरू करने के लिए Firebase को सर्वर से जोड़ना लेख देखें.

सामान्य फ़्लो की मदद से नया टास्क बनाया जाता है, उसे Cloud Tasks में जोड़ा जाता है, और टास्क का कॉन्फ़िगरेशन सेट किया जाता है:

Node.js के लिए

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);
    });

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")
  • सैंपल कोड, Nth टास्क के लिए Nवें मिनट की देरी को जोड़कर, टास्क को प्रोसेस करने की कोशिश करता है. इसका अनुवाद ~ 1 टास्क/मिनट ट्रिगर करने के लिए हो जाता है. ध्यान दें कि अगर आपको Cloud Tasks को किसी टास्क को तय समय पर ट्रिगर करना है, तो scheduleTime (Node.js) या schedule_time (Python) का भी इस्तेमाल किया जा सकता है.

  • सैंपल कोड वह ज़्यादा से ज़्यादा समय सेट करता है जो Cloud Tasks को किसी टास्क के पूरा होने का इंतज़ार करना होगा. सूची में मौजूद कॉन्फ़िगरेशन को फिर से कॉन्फ़िगर करके या समयसीमा पूरी होने तक, Cloud Tasks टास्क को फिर से प्रोसेस करेगा. सैंपल में, टास्क को पांच बार तक फिर से इस्तेमाल करने के लिए कॉन्फ़िगर किया गया है. हालांकि, अगर पूरी प्रोसेस (फिर से कोशिश करने की कोशिशें भी शामिल है) में पांच मिनट से ज़्यादा समय लगता है, तो टास्क अपने-आप रद्द हो जाता है.

टारगेट यूआरआई को वापस पाएं और शामिल करें

Cloud Tasks, टास्क की सूची में शामिल फ़ंक्शन के अनुरोधों की पुष्टि करने के लिए पुष्टि करने वाले टोकन बनाता है. इस वजह से, टास्क की सूची बनाते समय आपको फ़ंक्शन का Cloud Run यूआरएल तय करना होगा. हमारा सुझाव है कि आप प्रोग्राम के हिसाब से अपने फ़ंक्शन के यूआरएल को नीचे बताए गए तरीके से वापस पाएं:

Node.js के लिए

/**
 * Get the URL of a given v2 cloud function.
 *
 * @param {string} name the function's name
 * @param {string} location the function's location
 * @return {Promise<string>} The URL of the function
 */
async function getFunctionUrl(name, location="us-central1") {
  if (!auth) {
    auth = new GoogleAuth({
      scopes: "https://www.googleapis.com/auth/cloud-platform",
    });
  }
  const projectId = await auth.getProjectId();
  const url = "https://cloudfunctions.googleapis.com/v2beta/" +
    `projects/${projectId}/locations/${location}/functions/${name}`;

  const client = await auth.getClient();
  const res = await client.request({url});
  const uri = res.data?.serviceConfig?.uri;
  if (!uri) {
    throw new Error(`Unable to retreive uri for function at ${url}`);
  }
  return uri;
}

Python

def get_function_url(name: str, location: str = SupportedRegion.US_CENTRAL1) -> str:
    """Get the URL of a given v2 cloud function.

    Params:
        name: the function's name
        location: the function's location

    Returns: The URL of the function
    """
    credentials, project_id = google.auth.default(
        scopes=["https://www.googleapis.com/auth/cloud-platform"])
    authed_session = AuthorizedSession(credentials)
    url = ("https://cloudfunctions.googleapis.com/v2beta/" +
           f"projects/{project_id}/locations/{location}/functions/{name}")
    response = authed_session.get(url)
    data = response.json()
    function_url = data["serviceConfig"]["uri"]
    return function_url

समस्या हल करना

Cloud Tasks में लॉग इकट्ठा करने की सुविधा चालू करें

Cloud Tasks के लॉग में, गड़बड़ी की जानकारी से जुड़ी काम की जानकारी होती है. जैसे, टास्क से जुड़े अनुरोध की स्थिति. डिफ़ॉल्ट रूप से, Cloud Tasks के लॉग बंद रहते हैं, क्योंकि बड़ी संख्या में लॉग इस टास्क पर जनरेट हो सकते हैं. हमारा सुझाव है कि जब आप टास्क सूची के फ़ंक्शन को डेवलप और डीबग कर रहे हों, तब आप डीबग लॉग चालू करें. लॉग इन करने की सुविधा चालू करना देखें.

IAM अनुमतियां

टास्क की सूची बनाते समय या 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