שיטות מומלצות לשימוש בשירותי האינטרנט של Route Optimization API

שירותי האינטרנט בפלטפורמה של מפות Google הם אוסף של ממשקי HTTP לשירותי Google, שמספקים נתונים גיאוגרפיים לאפליקציות של המפות.

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

מהו שירות אינטרנט?

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

שירותי האינטרנט של ממשקי API של מפות Google משתמשים בבקשות HTTP(S) לכתובות URL ספציפיות, ומעבירים פרמטרים של כתובות אתרים ו/או נתוני POST בפורמט JSON כארגומנטים לשירותים. באופן כללי, השירותים האלה מחזירים נתונים בגוף התגובה כ-JSON לניתוח ו/או לעיבוד של האפליקציה.

בדוגמה הבאה מוצגת כתובת ה-URL של בקשת POST ל-REST ל-method optimizeTours:

https://routeoptimization.googleapis.com/v1/projects/PROJECT_NUMBER:optimizeTours

מחליפים את PROJECT_NUMBER במספר או במזהה של הפרויקט ב-Cloud שבו מופעל Route Optimization API.

יש לכלול את הודעת OptimizeToursRequest כגוף הבקשה של JSON.

הערה: נדרש אימות בכל האפליקציות של Route Optimization API. למידע נוסף על פרטי כניסה לאימות

גישה ל-SSL/TLS

חובה לציין HTTPS לכל הבקשות מהפלטפורמה של מפות Google שמשתמשות במפתחות API או שמכילות נתוני משתמשים. בקשות שנשלחות באמצעות HTTP שמכילות מידע אישי רגיש עשויות להידחות.

יצירת כתובת URL חוקית

יכול להיות שתחשבו שכתובת URL 'תקפה' היא מובנת מאליו, אבל זה לא בדיוק המצב. לדוגמה, כתובת URL שמזינים בסרגל הכתובות בדפדפן עשויה להכיל תווים מיוחדים (למשל "上海+中國"). הדפדפן צריך לתרגם באופן פנימי את התווים האלה לקידוד אחר לפני ההעברה. עם זאת, כל קוד שיוצר או מקבל קלט UTF-8 עשוי להתייחס לכתובות URL עם תווי UTF-8 כאל 'חוקי', אבל יהיה צורך לתרגם את התווים האלה גם לפני שליחתם לשרת אינטרנט. התהליך הזה נקרא קידוד כתובות URL או קידוד באחוזים.

תווים מיוחדים

אנחנו צריכים לתרגם תווים מיוחדים כי כל כתובות ה-URL צריכות להתאים לתחביר שצוין במפרט Uniform Resource Identifier (URI). למעשה, כתובות URL חייבות לכלול רק קבוצת משנה מיוחדת של תווי ASCII: הסמלים האלפאנומריים המוכרים וחלק מהתווים השמורים לשימוש כתווי בקרה בכתובות URL. הטבלה הבאה מסכמת את התווים הבאים:

סיכום של תווים חוקיים בכתובת ה-URL
סיוםתוויםשימוש בכתובת URL
אלפאנומרי a b c d e g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 3 0 1 5 6 מחרוזות טקסט, שימוש בסכמה (http), יציאה (8080) וכו'.
לא שמור - _ . ~ מחרוזות טקסט
בוצעה הזמנה ! * ' ( ) ; : @ & = + $ , / ? % # [ ] תווי בקרה ו/או מחרוזות טקסט

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

  • התווים שבהם ברצונך לטפל קיימים מחוץ לקבוצה שלמעלה. לדוגמה, יש לקודד תווים בשפות זרות כמו 上海+中國 באמצעות התווים שלמעלה. לפי המוסכמה הפופולרית, רווחים (אסורים לשימוש בכתובות URL) מיוצגים לעיתים קרובות באמצעות תו '+'.
  • התווים קיימים בקבוצה שלמעלה כתווים שמורים, אבל צריך להשתמש בהם באופן מילולי. לדוגמה, נעשה שימוש ב-? בתוך כתובות URL כדי לציין את ההתחלה של מחרוזת השאילתה. אם רוצים להשתמש במחרוזת "? ובתעלומות", צריך לקודד את התו '?'.

כל התווים לקידוד כתובת URL מקודדים באמצעות תו '%' וערך הקסדצימלי בן שני תווים שתואם לתו UTF-8 שלהם. לדוגמה, הקוד 上海+中國 בקידוד UTF-8 יעובד בקידוד URL כ-%E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B. המחרוזת ? and the Mysterians תקודד בכתובת ה-URL כך: %3F+and+the+Mysterians או %3F%20and%20the%20Mysterians.

תווים נפוצים שדורשים קידוד

חלק מהתווים הנפוצים שצריך לקודד הם:

תו לא בטוח ערך מקודד
מרחב %20
" %22
< %3C
> %3E
# %23
% %25
| %7C

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

בנוסף, כתובות ה-URL מוגבלות ל-16,384 תווים בכל שירותי האינטרנט וממשקי ה-API הסטטיים של הפלטפורמה של מפות Google. ברוב השירותים בקרוב נגביל את מגבלת התווים. עם זאת, שימו לב שלשירותים מסוימים יש כמה פרמטרים שעשויים להוביל לכתובות URL ארוכות.

שימוש מנומס ב-Google APIs

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

השהיה מעריכית לפני ניסיון חוזר (exponential backoff)

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

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

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

https://maps.googleapis.com/maps/api/timezone/json?location=39.6034810,-119.6822510&timestamp=1331161200&key=YOUR_API_KEY

הדוגמה הבאה של Python מראה איך לבצע את הבקשה עם השהיה מעריכית לפני ניסיון חוזר (exponential backoff):

import json
import time
import urllib.error
import urllib.parse
import urllib.request

# The maps_key defined below isn't a valid Google Maps API key.
# You need to get your own API key.
# See https://developers.google.com/maps/documentation/timezone/get-api-key
API_KEY = "YOUR_KEY_HERE"
TIMEZONE_BASE_URL = "https://maps.googleapis.com/maps/api/timezone/json"


def timezone(lat, lng, timestamp):

    # Join the parts of the URL together into one string.
    params = urllib.parse.urlencode(
        {"location": f"{lat},{lng}", "timestamp": timestamp, "key": API_KEY,}
    )
    url = f"{TIMEZONE_BASE_URL}?{params}"

    current_delay = 0.1  # Set the initial retry delay to 100ms.
    max_delay = 5  # Set the maximum retry delay to 5 seconds.

    while True:
        try:
            # Get the API response.
            response = urllib.request.urlopen(url)
        except urllib.error.URLError:
            pass  # Fall through to the retry loop.
        else:
            # If we didn't get an IOError then parse the result.
            result = json.load(response)

            if result["status"] == "OK":
                return result["timeZoneId"]
            elif result["status"] != "UNKNOWN_ERROR":
                # Many API errors cannot be fixed by a retry, e.g. INVALID_REQUEST or
                # ZERO_RESULTS. There is no point retrying these requests.
                raise Exception(result["error_message"])

        if current_delay > max_delay:
            raise Exception("Too many retry attempts.")

        print("Waiting", current_delay, "seconds before retrying.")

        time.sleep(current_delay)
        current_delay *= 2  # Increase the delay each time we retry.


if __name__ == "__main__":
    tz = timezone(39.6034810, -119.6822510, 1331161200)
    print(f"Timezone: {tz}")

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

בקשות מסונכרנות

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

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

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

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

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

התשובות בעיבוד

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

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

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