שיפור הביצועים

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

דחיסה באמצעות gzip

דרך פשוטה ונוחה לצמצם את רוחב הפס הדרוש לכל בקשה היא להפעיל דחיסת gzip. למרות שהפעולה הזו דורשת זמן נוסף במעבד (CPU) כדי לבטל את הדחיסה של התוצאות, ההתפשרות על עלויות הרשת בדרך כלל משתלמת מאוד.

כדי לקבל תגובה בקידוד gzip, עליך לעשות שני דברים: להגדיר כותרת Accept-Encoding ולשנות את סוכן המשתמש כך שיכיל את המחרוזת gzip. דוגמה לכותרות HTTP בפורמט תקין שאפשר להפעיל דחיסת gzip:

Accept-Encoding: gzip
User-Agent: my program (gzip)

עבודה עם משאבים חלקיים

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

יש שני סוגים של בקשות חלקיות:

  • תגובה חלקית: בקשה שבה מציינים אילו שדות רוצים לכלול בתגובה (באמצעות פרמטר הבקשה fields).
  • Patch: בקשת עדכון שבה שולחים רק את השדות שרוצים לשנות (יש להשתמש בפועל PATCH של HTTP).

בסעיפים הבאים יש מידע נוסף על שליחת בקשות חלקיות.

תגובה חלקית

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

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

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

דוגמה

בדוגמה הבאה אפשר לראות את השימוש בפרמטר fields עם API גנרי (בדיוני) מסוג "Demo".

בקשה פשוטה: בקשת HTTP זו מסוג GET משמיטה את הפרמטר fields ומחזירה את המשאב המלא.

https://www.googleapis.com/demo/v1

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

{
  "kind": "demo",
  ...
  "items": [
  {
    "title": "First title",
    "comment": "First comment.",
    "characteristics": {
      "length": "short",
      "accuracy": "high",
      "followers": ["Jo", "Will"],
    },
    "status": "active",
    ...
  },
  {
    "title": "Second title",
    "comment": "Second comment.",
    "characteristics": {
      "length": "long",
      "accuracy": "medium"
      "followers": [ ],
    },
    "status": "pending",
    ...
  },
  ...
  ]
}

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

https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)

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

200 OK
{
  "kind": "demo",
  "items": [{
    "title": "First title",
    "characteristics": {
      "length": "short"
    }
  }, {
    "title": "Second title",
    "characteristics": {
      "length": "long"
    }
  },
  ...
  ]
}

שימו לב שהתגובה היא אובייקט JSON שכולל רק את השדות שנבחרו ואת אובייקטי ההורה תוחמים שלהם.

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

סיכום התחביר של הפרמטרים של השדות

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

  • משתמשים ברשימה שמופרדת בפסיקים כדי לבחור שדות מרובים.
  • כדי לבחור שדה b שנמצא בתוך השדה a, משתמשים בפונקציה a/b. כדי לבחור שדה c מקונן בתוך b, משתמשים ב-a/b/c.

    חריג: בתגובות API שמשתמשות ברכיבי wrapper של "data", כשהתגובה מוצבת בתוך אובייקט data שנראה כמו data: { ... }, אין לכלול את 'data' במפרט של fields. הכללת אובייקט נתונים עם מפרט שדות כמו data/a/b גורמת לשגיאה. במקום זאת, צריך להשתמש במפרט של fields כמו a/b.

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

    לדוגמה: fields=items(id,author/email) מחזירה רק את מזהה הפריט ואת כתובת האימייל של המחבר עבור כל רכיב במערך הפריטים. אפשר גם לציין שדה משנה יחיד, שבו fields=items(id) היא שוות-ערך ל-fields=items/id.

  • אם צריך, אפשר להשתמש בתווים כלליים לחיפוש בשדות שנבחרו.

    לדוגמה: הפונקציה fields=items/pagemap/* בוחרת את כל האובייקטים במפת דפים.

דוגמאות נוספות לשימוש בפרמטר השדות

בדוגמאות הבאות יש תיאורים של ההשפעה של ערך הפרמטר fields על התגובה.

הערה: כמו בכל ערכי הפרמטרים של שאילתות, ערך הפרמטר fields חייב להיות מקודד בכתובת ה-URL. לשיפור הקריאוּת, אין הקידוד בדוגמאות במסמך זה.

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

הנה כמה דוגמאות ברמת האוסף:
דוגמאות השפעה
items מחזירה את כל הרכיבים במערך הפריטים, כולל את כל השדות בכל רכיב, אבל לא את השדות האחרים.
etag,items מחזירה גם את השדה etag וגם את כל הרכיבים במערך הפריטים.
items/title מחזירה רק את השדה title לכל הרכיבים במערך הפריטים.

בכל פעם שמוחזר שדה מקונן, התגובה כוללת את האובייקטים הפנימיים שבסוגריים. שדות ההורה לא כוללים שדות צאצא אחרים, אלא אם גם הם נבחרו באופן מפורש.
context/facets/label מחזירה רק את השדה label עבור כל החברים במערך facets, שממוקם בעצמו מתחת לאובייקט context.
items/pagemap/*/title לכל רכיב במערך הפריטים, מחזירה רק את השדה title (אם קיים) של כל האובייקטים שהם צאצאים של pagemap.

הנה כמה דוגמאות ברמת המשאב:
דוגמאות השפעה
title מחזירה את השדה title של המשאב המבוקש.
author/uri מחזירה את שדה המשנה uri של האובייקט author במשאב המבוקש.
links/*/href
מחזירה את השדה href של כל האובייקטים שהם צאצאים של links.
אפשר לבקש רק חלקים משדות ספציפיים באמצעות בחירות משנה.
כברירת מחדל, אם בבקשה שלכם מצוינים שדות מסוימים, השרת מחזיר את האובייקטים או את רכיבי המערך בשלמותם. אפשר לציין תשובה שתכלול רק שדות משנה מסוימים. ניתן לעשות זאת באמצעות התחביר של בחירת המשנה "( )", כמו בדוגמה הבאה.
דוגמה השפעה
items(title,author/uri) מחזירה רק את הערכים של title ושל uri של המחבר עבור כל רכיב במערך הפריטים.

טיפול בתשובות חלקיות

אחרי שהשרת מעבד בקשה חוקית שכוללת את פרמטר השאילתה fields, הוא שולח חזרה קוד מצב HTTP 200 OK יחד עם הנתונים המבוקשים. אם יש שגיאה בפרמטר של השאילתה fields או שהוא לא תקין מסיבה אחרת, השרת מחזיר קוד מצב HTTP 400 Bad Request, בצירוף הודעת שגיאה שאומרת למשתמש מה הייתה הבעיה בבחירת השדות (לדוגמה, "Invalid field selection a/b").

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

https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)

התגובה החלקית נראית כך:

200 OK
{
  "kind": "demo",
  "items": [{
    "title": "First title",
    "characteristics": {
      "length": "short"
    }
  }, {
    "title": "Second title",
    "characteristics": {
      "length": "long"
    }
  },
  ...
  ]
}

הערה: בממשקי API שתומכים בפרמטרים של שאילתות לחלוקה לדפים (maxResults ו-nextPageToken, לדוגמה), כדאי להשתמש בפרמטרים האלה כדי לצמצם את התוצאות של כל שאילתה לגודל שניתן לנהל. אחרת, ייתכן שהשיפור בביצועים עם תגובה חלקית לא יתממש.

תיקון (עדכון חלקי)

אפשר גם להימנע משליחת נתונים מיותרים כשמשנים משאבים. כדי לשלוח נתונים מעודכנים רק לשדות הספציפיים שמשנים, צריך להשתמש בפועל של HTTP PATCH. סמנטיקה של התיקון המתוארת במסמך זה שונה (ופשוטה יותר) מאשר בהטמעה הישנה יותר של GData של עדכון חלקי.

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

דוגמה

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

PATCH https://www.googleapis.com/demo/v1/324
Authorization: Bearer your_auth_token
Content-Type: application/json

{
  "title": "New title"
}

התשובה:

200 OK
{
  "title": "New title",
  "comment": "First comment.",
  "characteristics": {
    "length": "short",
    "accuracy": "high",
    "followers": ["Jo", "Will"],
  },
  "status": "active",
  ...
}

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

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

סמנטיקה של בקשת תיקון

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

  • הוספה: כדי להוסיף שדה שלא קיים, מציינים את השדה החדש ואת הערך שלו.
  • שינוי: כדי לשנות את הערך של שדה קיים, מציינים את השדה ומגדירים אותו לערך החדש.
  • מחיקה: כדי למחוק שדה, מציינים אותו ומגדירים אותו לערך null. לדוגמה, "comment": null. כדי למחוק אובייקט שלם (אם ניתן לשנות אותו), אפשר להגדיר אותו לערך null. אם אתם משתמשים בספריית הלקוח של Java API, צריך להשתמש במקום זאת ב-Data.NULL_STRING. לפרטים נוספים אפשר לעיין ב-JSON null.

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

שימוש תיקון במחזור קריאה-שינוי-כתיבה

מומלץ להתחיל באחזור תשובה חלקית עם הנתונים שאתם רוצים לשנות. הפעולה הזו חשובה במיוחד למשאבים שמשתמשים ב-ETags, כי כדי לעדכן את המשאב צריך לספק את הערך הנוכחי של ה-ETag בכותרת ה-HTTP של If-Match. אחרי שמקבלים את הנתונים, אפשר לשנות את הערכים שרוצים לשנות ולשלוח בחזרה את הייצוג החלקי שהשתנה עם בקשת תיקון. לפניכם דוגמה בהנחה שמשאב ההדגמה משתמש בתגי ETags:

GET https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics
Authorization: Bearer your_auth_token

זו התגובה החלקית:

200 OK
{
  "etag": "ETagString"
  "title": "New title"
  "comment": "First comment.",
  "characteristics": {
    "length": "short",
    "level": "5",
    "followers": ["Jo", "Will"],
  }
}

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

PATCH https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics
Authorization: Bearer your_auth_token
Content-Type: application/json
If-Match: "ETagString"
{
  "etag": "ETagString"
  "title": "",                  /* Clear the value of the title by setting it to the empty string. */
  "comment": null,              /* Delete the comment by replacing its value with null. */
  "characteristics": {
    "length": "short",
    "level": "10",              /* Modify the level value. */
    "followers": ["Jo", "Liz"], /* Replace the followers array to delete Will and add Liz. */
    "accuracy": "high"          /* Add a new characteristic. */
  },
}

השרת מגיב עם קוד מצב HTTP 200 OK ואת הייצוג החלקי של המשאב המעודכן:

200 OK
{
  "etag": "newETagString"
  "title": "",                 /* Title is cleared; deleted comment field is missing. */
  "characteristics": {
    "length": "short",
    "level": "10",             /* Value is updated.*/
    "followers": ["Jo" "Liz"], /* New follower Liz is present; deleted Will is missing. */
    "accuracy": "high"         /* New characteristic is present. */
  }
}

יצירה ישירה של בקשת תיקון

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

הערה: אפשר להשתמש בכותרת HTTP "If-Match: *" כדי לאלץ תיקון לעבור כשתגי ETags נמצאים בשימוש. אם תעשו זאת, אין צורך לבצע את הקריאה לפני הכתיבה.

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

PATCH https://www.googleapis.com/demo/v1/324?fields=comment,characteristics
Authorization: Bearer your_auth_token
Content-Type: application/json

{
  "comment": "A new comment",
  "characteristics": {
    "volume": "loud",
    "accuracy": null
  }
}

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

טיפול בתגובה לתיקון

לאחר עיבוד בקשת תיקון חוקית, ה-API מחזיר קוד תגובת HTTP מסוג 200 OK יחד עם הייצוג המלא של המשאב שהשתנה. אם ה-API משתמש ב-ETags, השרת מעדכן את ערכי ETag כשהוא מעבד בהצלחה בקשת תיקון, בדיוק כמו שהוא עושה ב-PUT.

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

אם בקשת תיקון מובילה למצב משאב חדש שאינו תקין מבחינה תחבירית או סמנטית, השרת מחזיר קוד סטטוס HTTP של 400 Bad Request או 422 Unprocessable Entity ומצב המשאב נשאר ללא שינוי. לדוגמה, אם תנסו למחוק את הערך בשדה חובה, השרת יחזיר שגיאה.

סימון חלופי כשאין תמיכה בפועל של HTTP מסוג PATCH

אם חומת האש לא מאפשרת בקשות PATCH HTTP, יש לשלוח בקשת HTTP POST ולהגדיר את כותרת הביטול ל-PATCH, כפי שמוצג בהמשך:

POST https://www.googleapis.com/...
X-HTTP-Method-Override: PATCH
...

ההבדל בין תיקון לעדכון

בפועל, כששולחים נתונים לבקשת עדכון שמשתמשת בפועל PUT של HTTP, צריך לשלוח רק את השדות האלה (חובה או אופציונליים). אם שולחים ערכים לשדות שהוגדרו על ידי השרת, המערכת תתעלם מהם. נראה שזו דרך נוספת לבצע עדכון חלקי, אבל לגישה הזו יש כמה מגבלות. בעדכונים שמשתמשים בפעל'PUT' של HTTP, הבקשה תיכשל אם לא תספקו את הפרמטרים הנדרשים, והנתונים שהוגדרו יימחקו אם לא תספקו פרמטרים אופציונליים.

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