שיטות מומלצות לשימוש בשירותי האינטרנט של Map Management API

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

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

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

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

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

בדוגמה הבאה מוצגת בקשת REST GET לשימוש במתודה list Map Configs:

https://mapmanagement.googleapis.com/v2beta/projects/PROJECT_NUMBER_OR_ID/mapConfigs

בבקשה צריך לכלול טוקן OAuth בכותרת Authorization header של הבקשה.

גישה ל-SSL/TLS

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

יצירת כתובת URL תקינה

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

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

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

סיכום של תווים חוקיים בכתובת URL
הגדרהתוויםשימוש בכתובת URL
אלפאנומרי 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 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 0 1 2 3 4 5 6 7 8 9 מחרוזות טקסט, שימוש בסכימה (http), יציאה (8080) וכו'.
לא שמור - _ . ~ מחרוזות טקסט
בוצעה הזמנה ! * ' ( ) ; : @ & = + $ , / ? % # [ ] תווי בקרה או מחרוזות טקסט

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

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

כל התווים שמקודדים בהתאמה לכתובות 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 שמתקבלת מקלט של משתמשים. לדוגמה, משתמש יכול להזין כתובת כ-"5th&Main St." באופן כללי, צריך ליצור את כתובת ה-URL מהחלקים שלה, ולהתייחס לכל קלט של משתמשים כאל תווים מילוליים.

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

שימוש הוגן ב-Google APIs

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

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

במקרים נדירים, יכול להיות שמשהו ישתבש בהגשת הבקשה שלכם. יכול להיות שתקבלו קוד תגובה 4XX או 5XX HTTP, או שהחיבור ל-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 אפשר לראות איך לשלוח את הבקשה עם השהיה מעריכית לפני ניסיון חוזר:

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}")

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

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

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

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

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

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

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

עיבוד תשובות

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

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

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