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

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

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

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

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

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

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

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

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

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

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

תגובה חלקית

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

כדי לבקש תגובה חלקית, יש להשתמש בפרמטר הבקשה 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)

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

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

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

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

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

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

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

    חריג לכלל הזה:בתגובות API שנעשה בהן שימוש ב-wrappers של "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 גנרי (בדיוני) מסוג "Demo". למשאב יש גם הערה, קבוצת מאפיינים, סטטוס ושדות רבים נוספים, אבל הבקשה הזו שולחת רק את השדה 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

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

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

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

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

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