התראות על שינוי אובייקטים

אפשר להשתמש בהתראות על שינוי אובייקטים כדי להודיע לאפליקציה כשאובייקט מתעדכן או מתווסף לקטגוריה.

האם צריך להשתמש בהתראות על שינוי אובייקטים?

בדרך כלל לא מומלץ להשתמש בהתראות על שינוי אובייקטים. הכלי המומלץ ליצירת התראות שעוקבות אחר שינויים באובייקטים בקטגוריות של Cloud Storage הוא התראות Pub/Sub של Cloud Storage, כי הוא מהיר יותר, גמיש יותר, קל יותר להגדרה וחסכוני יותר. למדריך מפורט על הגדרת התראות Pub/Sub בשביל Cloud Storage, ראו הגדרת התראות Pub/Sub בשביל Cloud Storage.

האופן שבו פועלות התראות על שינוי אובייקטים

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

כשממלאים את בקשת המעקב, נוצר ערוץ התראות חדש. ערוץ התראות הוא האמצעי שבאמצעותו נשלחת הודעת התראה לאפליקציה שעוקבת אחרי קטגוריה מסוימת. נכון לעכשיו, יש תמיכה רק בסוג אחד של ערוץ התראות, הוק (hook) אינטרנט.

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

האיור הבא מציג דוגמה לתהליך של זרימת נתונים לאפליקציה שמעבדת התראות על שינויים. אפשר להשתמש בכל שרת אפליקציות שיכול לקבל בקשות HTTPS POST כדי לעבד התראות על שינויים.

הרכיבים של התראה על שינוי אובייקט
הרכיבים של התראה על שינוי אובייקט

פרטי התראה על שינוי אובייקט

הסברים על המונחים

הטבלה הבאה מכילה תיאור של מספר מונחים המופיעים במשאבי העזרה בנושא התראה על שינוי אובייקט:

מונח תיאור
כתובת ה-URL של האפליקציה כתובת ה-URL של האפליקציה. זוהי הכתובת שאליה יישלחו ההתראות. שימו לב שזו חייבת להיות כתובת URL מסוג HTTPS, אי אפשר להשתמש בכתובות URL מסוג HTTP.
מזהה ערוץ המזהה של ערוץ התראות. חייב להיות ייחודי בקטגוריה מסוימת. כלומר, אם יש מספר ערוצי התראות לקטגוריה אחת, לכל ערוץ התראות צריך להיות מזהה ערוץ נפרד. המזהה הזה יישלח לאפליקציה יחד עם כל הודעת התראה.
מזהה המשאב מזהה אטום של המשאב הנמצא במעקב. צריך לציין את מזהה המשאב כדי לעצור ערוץ התראות. אפשר לאחזר את המזהה הזה מהתשובה לבקשת מעקב או מהכותרת X-Goog-Resource-Id של הודעות לגבי אירוע התראה.
אסימון הלקוח (אופציונלי) אפשר להשתמש באסימוני לקוח כדי לאמת אירועי התראות. כדי לעשות את זה, צריך להגדיר אסימון לקוח בהתאמה אישית יחד עם הבקשה למעקב. הודעות ההתראות יכילו את האסימון הזה כדי לאפשר אימות שהן אותנטיות.

מעקב אחרי קטגוריה

כדי להתחיל מעקב אחרי התראות על שינויים בקטגוריה, אפשר להשתמש בפקודה gsutil notification watchbucket:

gsutil notification watchbucket [-i ChannelId] [-t ClientToken] ApplicationUrl gs://BucketName

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

כדי לקבל מידע נוסף על הפקודה הזו, מריצים את הפקודה gsutil help notification watchbucket.

דוגמה לבקשת POST שנוצרה על-ידי gsutil לצורך מעקב אחר קטגוריה:

POST /storage/v1/b/BucketName/o/watch?alt=json HTTP/1.1
Host: storage.googleapis.com
Content-Length: 200
User-Agent: google-api-python-client/1.0
Content-Type: application/json
Authorization: Bearer oauth2_token

{
  "token": "ClientToken",
  "type": "web_hook",
  "id": "ChannelId",
  "address": "ApplicationUrl"
}

הרשאה לשליחת התראות

במהלך המעקב אחרי קטגוריה, ערוץ ההתראות שנוצר ישויך לפרויקט במסוף Google Cloud של האפליקציה שממנה נשלחה בקשת ה-API. המשמעות היא, לדוגמה, שאם משתמשים מעניקים גישה לאפליקציה מותקנת או לאפליקציית אינטרנט דרך תהליך OAuth2, ערוץ ההתראות שנוצר על-ידי האפליקציה משויך לפרויקט של האפליקציה, ולא לפרויקט המכיל את הקטגוריה שאחריה עוקבים.

יש שני שלבים להגדרת הרשאה בתרחיש של התראה על שינוי אובייקטים:

יצירת חשבון שירות

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

רצוי להשתמש בחשבון שירות קיים או ליצור אחד חדש ו-להוריד את המפתח הפרטי המשויך אליו.

הגדרת gsutil לשימוש בחשבון השירות

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

כדי ליצור פרטי כניסה בהתאם לחשבון השירות:

  1. צריך לוודא שמשתמשים בגרסה העדכנית של CLI של gcloud. אפשר לעדכן את הרכיבים על-ידי הרצה של:
    gcloud components update
    
  2. משתמשים בפקודה gcloud auth activate-service-account ומציינים את כתובת האימייל של חשבון השירות ואת המפתח הפרטי.
    gcloud auth activate-service-account service-account-email --key-file path/to/key.p12
    

    כאשר:

    • service-account-email הוא כתובת האימייל של חשבון השירות. זה ייראה בערך כך: 1234567890123-abcdefghijklmonpqrstuvwxz01234567@developer.gserviceaccount.com.
    • path/to/key.p12 הוא המפתח שהתבקשתם להוריד כשיצרתם את חשבון השירות. אם איבדתם את המפתח, אפשר לחזור לדף פרטי כניסה במסוף Google Cloud וליצור מפתח חדש.
  3. מוודאים שחשבון השירות הוא החשבון הפעיל עם פרטי הכניסה.
    $ gcloud auth list
    Credentialed accounts:
    - 1234567890123-abcdefghijklmonpqrstuvwxz01234567@developer.gserviceaccount.com (active)
    

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

הסרת ערוץ התראות

כדי לעצור ערוץ התראות, משתמשים בפקודה gsutil notification stopchannel:

gsutil notification stopchannel ChannelId ResourceId

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

כדי לקבל מידע נוסף על הפקודה הזו, מריצים את הפקודה gsutil help notification stopchannel.

דוגמה לבקשת POST שנוצרה על-ידי gsutil לצורך עצירת ערוץ:

POST /storage/v1/channels/stop HTTP/1.1
Host: storage.googleapis.com
Content-Length: 200
User-Agent: google-api-python-client/1.0
Content-Type: application/json
Authorization: Bearer oauth2_token

{
  "resourceId": "ResourceId",
  "id": "ChannelId"
}

סוגי הודעות על אירועי התראות

סנכרון

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

ההתראה נשלחת כבקשת POST לכתובת ה-URL של האפליקציה שהוגדרה. אין גוף בבקשה. המטא-נתונים של התראת הסנכרון נמצאים בכותרות של הבקשה. דוגמה לבקשה של התראת סנכרון:

POST /ApplicationUrlPath
Accept: */*
Content-Type: application/json; charset="utf-8"
Content_Length: 0
Host: ApplicationUrlHost
X-Goog-Channel-Id: ChannelId
X-Goog-Channel-Token: ClientToken
X-Goog-Resource-Id: ResourceId
X-Goog-Resource-State: sync
X-Goog-Resource-Uri: https://storage.googleapis.com/storage/v1/b/BucketName/o?alt=json

הוספה, עדכון או מחיקה של אובייקט

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

ההתראה נשלחת כבקשת POST לכתובת ה-URL של האפליקציה שהוגדרה. גוף הבקשה מכיל הודעה מקודדת באמצעות JSON כפי שמוצג בבקשת ההתראה הבאה:

POST /ApplicationUrlPath
Accept: */*
Content-Length: 1097
Content-Type: application/json; charset="utf-8"
Host: ApplicationUrlHost
X-Goog-Channel-Id: ChannelId
X-Goog-Channel-Token: ClientToken
X-Goog-Resource-Id: ResourceId
X-Goog-Resource-State: ResourceState
X-Goog-Resource-Uri: https://storage.googleapis.com/storage/v1/b/BucketName/o?alt=json

{
 "kind": "storage#object",
 "id": "BucketName/ObjectName",
 "selfLink": "https://www.googleapis.com/storage/v1/b/BucketName/o/ObjectName",
 "name": "ObjectName",
 "bucket": "BucketName",
 "generation": "1367014943964000",
 "metageneration": "1",
 "contentType": "application/octet-stream",
 "updated": "2013-04-26T22:22:23.832Z",
 "size": "10",
 "md5Hash": "xHZY0QLVuYng2gnOQD90Yw==",
 "mediaLink": "https://storage.googleapis.com/storage/v1/b/BucketName/o/ObjectName?generation=1367014943964000&alt=media",
 "owner": {
  "entity": "user-jane@gmail.com"
 },
 "crc32c": "C7+82w==",
 "etag": "COD2jMGv6bYCEAE="
}
כאשר ResourceState הוא:
  • exists - להוספות ולעדכונים של אובייקטים.
  • not_exists - למחיקות של אובייקטים.

כאשר התוכן של הודעת ה-JSON מכיל את הייצוג הנוכחי של האובייקט כפי שמתואר בתיאור משאב האובייקט.

מסירה אמינה

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

  • אם הניסיון למסירת התראה נכשל, יבוצעו ניסיונות נוספים. מרווח הזמן בין ניסיונות מסירה נוספים נקבע על-ידי אלגוריתם השהיה מעריכית לפני ניסיון חוזר (exponential backoff) שמתחיל בניסיון חוזר 30 שניות אחרי הכשל הראשוני. המסירות הבאות מתבצעות במרווחי זמן הולכים וגדלים, עד למרווח זמן מקסימלי של 90 דקות. חשוב לשים לב שמרווחי הזמן העוקבים של הניסיונות החוזרים כוללים מעט אקראיות, כך שהם לא מתרחשים בערכים מעריכיים מדויקים. אחרי מרווח הזמן המרבי של 90 דקות לניסיון חוזר, מתבצעים ניסיונות חוזרים נוספים בכל 90 דקות למשך 7 ימים. אם אי אפשר למסור את ההתראה בפרק הזמן הזה, היא תימחק באופן סופי.
  • אם אי אפשר ליצור קשר עם האפליקציה לאחר 20 שניות או אם האפליקציה משיבה את אחד מקודי התשובה הבאים של HTTP, ניסיון מסירת ההתראה נחשב כנכשל ומנסים שוב:
    • ‫‎500 Internal Server Error
    • ‫‎502 Bad Gateway
    • ‫‎503 Service Unavailable
    • ‫‎504 Gateway Timeout
  • אם האפליקציה משיבה את אחד מקודי התשובה הבאים של HTTP, ההתראה נחשבת כהתראה שנמסרה בהצלחה:
    • ‫‎102 Processing
    • ‫‎200 OK
    • ‫‎201 Created
    • ‫‎202 Accepted
    • ‫‎204 No Content
  • כל קוד תשובה אחר של HTTP שהוחזר על-ידי האפליקציה נחשב כנכשל באופן סופי ולא יתבצע ניסיון חוזר.

דוגמה לאפליקציית לקוח

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

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

ציר זמן להתראות על שינוי אובייקטים
ציר זמן להתראות על שינוי אובייקטים

האפליקציה לדוגמה מכילה מחלקה בשם MainPage. כשמשתמשים מעדכנים או מוסיפים אובייקט לקטגוריה, המחלקה MainPage מעבדת את אירוע ההתראה. כדי לפשט את הדברים, ה-method post שמבצעת את העיבוד בפועל רק מתעדת הודעה עם שעת קבלת ההתראה. אפשר להחליף את הקוד הזה בלוגיקת העיבוד בפועל. אם עדיין לא התקדמתם בפיתוח אפליקציות של App Engine, מומלץ לפרוס אפליקציה לדוגמה או לפעול לפי המדריך לפני שממשיכים.

  1. הגדרת האפליקציה.
    יוצרים את קובץ התצורה app.yaml כדי לציין את אפליקציית הלקוח המטפלת באירועי התראות על שינוי בקטגוריה.
    application: APPLICATION
    version: 1
    runtime: python38
    api_version: 1
    threadsafe: true
    
    handlers:
    - url: /.*
      script: change_notification_client.app
    
  2. יצירת האפליקציה.
    הדוגמה הבאה מממשת אפליקציית לקוח לטיפול באירועי התראות על שינוי בקטגוריה. מעניקים את השם change_notification_client.py, ולאחר מכן פורסים את האפליקציה:
    """Notification handling for Google Cloud Storage."""
    
    import json
    import logging
    
    import webapp2
    
    class MainPage(webapp2.RequestHandler):
      """Process notification events."""
      def get(self):
        logging.info("Get request to notification page.")
        self.response.write("Welcome to the notification app.")
    
      def post(self):  # pylint: disable-msg=C6409
        """Process the notification event.
    
        This method is invoked when the notification channel is first created with
        a sync event, and then subsequently every time an object is added to the
        bucket, updated (both content and metadata) or removed. It records the
        notification message in the log.
        """
    
        logging.debug(
            '%s\n\n%s',
            '\n'.join(['%s: %s' % x for x in self.request.headers.iteritems()]),
            self.request.body)
    
        # The following code is for demonstration. Replace
        # it with your own notification processing code.
    
        if 'X-Goog-Resource-State' in self.request.headers:
          resource_state = self.request.headers['X-Goog-Resource-State']
          if resource_state == 'sync':
            logging.info('Sync message received.')
          else:
            an_object = json.loads(self.request.body)
            bucket = an_object['bucket']
            object_name = an_object['name']
            logging.info('%s/%s %s', bucket, object_name, resource_state)
        else:
          logging.info("Other post.")
    
    logging.getLogger().setLevel(logging.DEBUG)
    app = webapp2.WSGIApplication([('/', MainPage)], debug=True)
    
  3. הקצאת הרשאת הגישה של האפליקציה לקטגוריה.
    אם הקטגוריה נמצאת בבעלות של חשבון שירות אחר מזה של אפליקציית App Engine, אפשר להריץ את הפקודה הבאה כדי להעניק לאפליקציה גישת בעלים לקטגוריה:
    gsutil acl ch -u ApplicationId@appspot.gserviceaccount.com:OWNER gs://BucketName
    
  4. מתחילים לעקוב אחר שינויים באובייקטים בקטגוריה.
    יוצרים ערוץ התראות בשביל האפליקציה על-ידי צפייה בקטגוריה באמצעות gsutil:
    gsutil notification watchbucket ApplicationUrl gs://BucketName
    
    כאשר ApplicationUrl הוא כתובת ה-URL של אפליקציית App Engine למשל, ‫https://ApplicationId.appspot.com/.
  5. בדיקת האפליקציה.
    כדי לבדוק אם האפליקציה עובדת כצפוי, מבצעים את הפעולות הבאות:
    1. כדי לוודא שהאפליקציה פרוסה ועובדת כראוי, מבצעים את הפקודה הבאה של curl:
      curl -X Post https://APPLICATION_ID.appspot.com
      
      אם השתמשתם בשם דומיין משלכם כדי לפרוס את האפליקציה, צריך להשתמש בו במקום ב-appspot.com בפקודה הקודמת.
    2. עוברים לדף Logging של הפרויקט. אם צריך, מרעננים את רשימת ההודעות ביומן. מוודאים שהודעת היומן שנשלחה על-ידי האפליקציה רשומה ביומן.
    3. מוסיפים אובייקט לקטגוריה. אפשר להשתמש בכלי gsutil באופן הבא:
      gsutil cp ObjectName gs://BucketName/
      
      האפליקציה Cloud Storage שולחת התראה לאפליקציה, שלאחר מכן רושמת הודעה.
    4. עוברים לדף Logging של הפרויקט. מרעננים את רשימת ההודעות שנרשמו ביומן ומוצאים את ההודעה של העתקת האובייקט.
  6. הסרת ערוץ ההתראות
    מסירים את ערוץ ההתראות על-ידי ציון מזהה הערוץ ומזהה המשאב שהוחזרו כשהונפקה פקודת ההתראה למעקב אחרי הקטגוריה.
    gsutil notification stopchannel CHANNEL_ID RESOURCE_IDENTIFIER