יצירת משימות Push

בדף הזה מוסבר איך ליצור משימות ולהוסיף אותן לתורים של הודעות Push. כשרוצים לעבד משימה, צריך ליצור אובייקט משימה חדש ולהציב אותו בתור. אתם יכולים לציין במפורש את השירות ואת ה-handler שמטפלים במשימה, ואם רוצים, להעביר ל-handler נתונים ספציפיים למשימה. אפשר גם לכוונן את ההגדרות של המשימה, למשל לתזמן מועד עתידי לביצוע שלה או להגביל את מספר הפעמים שבהן המשימה תנסה להתבצע מחדש אם היא תיכשל.

יצירת משימה חדשה

כדי ליצור משימה ולהוסיף אותה לתור, קוראים לפונקציה taskqueue.add().

ציון שירות העובדים

כשמשימה יוצאת מהתור שלה, שירות תור המשימות שולח אותה לשירות של עובד. לכל משימה יש יעד וכתובת URL, שקובעים איזה שירות ומטפל יבצעו בסופו של דבר את המשימה.

target

היעד מציין את השירות שיקבל את בקשת ה-HTTP כדי לבצע את המשימה. זוהי מחרוזת שמציינת שירות/גרסה/מופע באחד מהפורמטים הקנוניים. הטפסים הכי נפוצים הם:

    service
    version.service
    instance.version.service

מחרוזת היעד מתווספת לפני שם הדומיין של האפליקציה. יש שלוש דרכים להגדיר את היעד למשימה:

  • מצהירים על היעד כשיוצרים את המשימה. אפשר להגדיר את היעד באופן מפורש באמצעות הפרמטר target בפונקציה taskqueue.add(). דוגמה: ראו למעלה.

  • כשמגדירים תור ב-queue.yaml, צריך לכלול הנחיית target, כמו בהגדרה של queue-blue. כל המשימות שנוספו לתור עם target ישתמשו ביעד הזה, גם אם הוקצה למשימה יעד אחר בזמן היצירה.

  • אם לא מצוין יעד באף אחת משתי השיטות הקודמות, היעד של המשימה הוא הגרסה של השירות שמוסיפה אותה לתור. שימו לב: אם מוסיפים משימה לתור משירות ברירת המחדל ומגרסת ברירת המחדל באופן הזה, וגרסת ברירת המחדל משתנה לפני שהמשימה מופעלת, היא תופעל בגרסת ברירת המחדל החדשה.

url

url בוחר באחד מהמטפלים בשירות היעד, שיבצע את המשימה.

הערך url צריך להתאים לאחת מתבניות כתובות ה-URL של ה-handler בשירות היעד. הפרמטר url יכול לכלול פרמטרים של שאילתה אם השיטה שצוינה במשימה היא GET או PULL. אם לא מציינים url, נעשה שימוש בכתובת ה-URL שמוגדרת כברירת מחדל /_ah/queue/[QUEUE_NAME], כאשר [QUEUE_NAME] הוא שם התור של המשימה.

העברת נתונים אל ה-handler

אפשר להעביר נתונים ל-handler כפרמטרים של שאילתה בכתובת ה-URL של המשימה, אבל רק אם השיטה שצוינה במשימה היא GET או PULL.

אפשר גם להשתמש בשדות הבאים כדי להוסיף נתונים למשימה:

  • payload, שמעביר את נתוני המשימה בגוף של בקשת ה-HTTP.
  • params

שלושת הקריאות האלה שוות:

taskqueue.add(method=GET, url='/update-counter?key=blue', target='worker')
taskqueue.add(url='/update-counter', params={'key': 'blue'}, target='worker')
taskqueue.add(url='/update-counter', payload="{'key': 'blue'}", target='worker')

מתן שם למשימה

כשיוצרים משימה חדשה, App Engine מקצה למשימה שם ייחודי כברירת מחדל. עם זאת, אתם יכולים להקצות שם משלכם למשימה באמצעות הפרמטר name. יתרון בהקצאת שמות משלכם למשימות הוא שהמערכת מסירה כפילויות של משימות עם שמות, כך שאתם יכולים להשתמש בשמות משימות כדי להבטיח שמשימה תתווסף רק פעם אחת. הסרת הכפילויות נמשכת 9 ימים אחרי שהמשימה מסתיימת או נמחקת.

שימו לב: לוגיקת ביטול הכפילויות יוצרת תקורה משמעותית בביצועים, וכתוצאה מכך עלייה בזמני האחזור ועלייה פוטנציאלית בשיעורי השגיאות שקשורים למשימות עם שמות. העלויות האלה יכולות להיות גבוהות במיוחד אם שמות המשימות הם עוקבים, כמו חותמות זמן. לכן, אם אתם מקצים שמות משלכם, מומלץ להשתמש בקידומת עם פיזור טוב לשמות המשימות, כמו גיבוב של התוכן.

אם אתם מקצים שמות משלכם למשימות, שימו לב שהאורך המקסימלי של השם הוא 500 תווים, והשם יכול להכיל אותיות רישיות וקטנות, מספרים, קווים תחתונים ומקפים.

הוספת משימות באופן אסינכרוני

כברירת מחדל, הקריאות שמוסיפות משימות לתורים הן סינכרוניות. ברוב התרחישים, קריאות סנכרוניות פועלות בצורה תקינה. הוספת משימה לתור היא בדרך כלל פעולה מהירה. יש אחוז קטן של פעולות להוספת משימות שיכולות להימשך הרבה יותר זמן, אבל הזמן החציוני להוספת משימה הוא פחות מ-5 אלפיות השנייה.

אי אפשר לבצע באצ'ינג של פעולות להוספת משימות לתורים שונים, ולכן Task Queue API מספק גם קריאות אסינכרוניות שמאפשרות להוסיף את המשימות האלה במקביל, וכך לצמצם עוד יותר את זמן האחזור. האפשרות הזו שימושית אם אתם מפתחים אפליקציה שרגישה מאוד לזמן אחזור, וצריכה לבצע כמה פעולות של הוספת משימות לכמה תורים שונים בו-זמנית.

אם רוצים לבצע קריאות אסינכרוניות לתור משימות, צריך להשתמש בשיטות האסינכרוניות שמסופקות על ידי המחלקה . מחלקה Queue ואובייקט RPC. מתקשרים אל get_result() באובייקט RPC שהוחזר כדי לאלץ את השלמת הבקשה. כשמוסיפים משימות באופן אסינכרוני לעסקה, צריך לקרוא ל-get_result() באובייקט RPC לפני שמבצעים את העסקה, כדי לוודא שהבקשה הסתיימה

הוספת משימות לתור בטרנזקציות של Cloud Datastore

אפשר להוסיף משימה לתור כחלק מטרנזקציית Datastore, כך שהמשימה תתווסף לתור – ומובטח שהיא תתווסף לתור – רק אם הטרנזקציה תאושר בהצלחה. משימות שנוספו ב טרנזקציה נחשבות לחלק ממנה, ויש להן את אותה רמה של טרנזקציה .

אפליקציה לא יכולה להוסיף יותר מחמש משימות טרנזקציונליות לתורי משימות במהלך טרנזקציה אחת. למשימות טרנזקציונליות אסור להכיל שמות שצוינו על ידי המשתמש.

בדוגמת הקוד הבאה אפשר לראות איך להוסיף משימות טרנזקציונליות לתור דחיפה (push queue) כחלק מטרנזקציה ב-Datastore:

from google.appengine.api import taskqueue
from google.appengine.ext import ndb

@ndb.transactional
def do_something_in_transaction():
  taskqueue.add(url='/path/to/my/worker', transactional=True)
  #...

do_something_in_transaction()

שימוש ב deferred task library במקום בשירות worker

הגדרת handler לכל משימה נפרדת (כפי שמתואר בקטעים הקודמים) יכולה להיות מסורבלת, וכך גם סדרות וביטול סדרות של ארגומנטים מורכבים למשימה – במיוחד אם יש לכם הרבה משימות מגוונות אבל קטנות שאתם רוצים להריץ בתור. ערכת ה-SDK של Python כוללת ספריה (google.appengine.ext.deferred) שחושפת פונקציה פשוטה שמאפשרת לכם לעקוף את כל העבודה של הגדרת מטפלים ייעודיים במשימות וסדרות וביטול סדרות של הפרמטרים שלכם.

כדי להשתמש בספרייה הזו, צריך להוסיף את deferred המובנה ל-app.yaml. מידע נוסף זמין בקטע בנושא רכיבי handler מובנים במאמר העזר בנושא app.yaml.

כדי להשתמש בספרייה deferred, פשוט מעבירים את הפונקציה ואת הארגומנטים שלה אל deferred.defer():

import logging

from google.appengine.ext import deferred

def do_something_expensive(a, b, c=None):
    logging.info("Doing something expensive!")
    # Do your work here

# Somewhere else
deferred.defer(do_something_expensive, "Hello, world!", 42, True)

הספרייה deferred אורזת את בקשה להפעלת פונקציה ואת הארגומנטים שלה, ואז מוסיפה אותה לתור המשימות. כשהמשימה מופעלת, ספריית deferred מפעילה את do_something_expensive("Hello, world!", 42, True).

עבודה עם משימות באפליקציה לפי עקרון ה-Multi-tenancy

כברירת מחדל, תורי push משתמשים במרחב השמות הנוכחי כפי שהוגדר במנהל מרחבי השמות בזמן יצירת המשימה. אם האפליקציה משתמשת בגישה מרובת דיירים, כדאי לעיין ב-Namespaces API.

המאמרים הבאים